English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Rust-Ennumerationen

Die Enumeration in Rust ist nicht so einfach wie in anderen Programmiersprachen, aber sie kann dennoch sehr einfach verwendet werden:

#[derive(Debug)]

enum Book {
    Papier, Elektronisch
}

fn main() {
    let book = Buch::Papier;
    println!("{:?}", Buch);
}

Laufender Output:

Papier

Bücher werden in Papierbücher (Papierbuch) und eBooks (Elektronisches Buch) unterteilt.

Wenn Sie derzeit einen Buchverwaltungssystem entwickeln, müssen Sie die verschiedenen Eigenschaften der beiden Arten von Büchern beschreiben (Bücher haben eine Signaturnummer für Papierbücher und eBooks haben nur URL), Sie können Tuple-Attribute hinzufügen, um Enumerationselemente zu beschreiben:

enum Buch {
    Papier(u32),
    Elektronisch(String),
}
let book = Buch::Papier(1001);
let ebook = Buch::Elektronisch(String::from("url://..."));

Wenn Sie den Namen eines Attributs geben möchten, können Sie die Struktur语法 verwenden:

enum Buch {
    Papier { index: u32 },
    Elektronisch { url: String },
}
let Buch = Buch::Papier{index: 1001};

Although it can be named in this way, please note that enum class bound properties cannot be accessed like structure fields. The method of accessing them is in the match syntax.

match syntax

The purpose of enums is to classify a certain type of thing, and the purpose of classification is to describe different situations. Based on this principle, enum types are often processed by branch structures (similar to switch in many languages). The switch syntax is classic, but it is not supported in Rust. Many languages have abandoned switch because switch is prone to chaining execution problems due to forgetting to add break. Languages like Java and C# eliminate this situation through safety checks.

Rust implements branch structures through match statements. First, let's get to know how to use match to process enum types:

fn main() {
    enum Book {
        Papery &123;index: u32},
        Electronic &123;url: String &125;,
    }
   
    let book = Book::Papery &123;index: 1001};
    let ebook = Book::Electronic&123;url: String::from&40;"url..."&41;};
   
    match book &123;
        Book::Papery &123; index &125; => {
            println!("Papery book {}", index&41;;
        },
        Book::Electronic &123; url &125; => {
            println!("E-book {}", url&41;;
        }
    }
}

Running result:

Papery book 1001

The match block can also be treated as a function expression and can also have a return value:

match enum class example {
    Classification1 => return value expression,
    Classification2 => return value expression,
    ...
}

However, all return value expression types must be the same!

If the attached properties of an enum type are defined as tuples, a temporary name must be specified in the match block:

enum Book {
    Papery(u32),
    Electronic &123;url: String &125;,
}
let book = Book::Papery &40;1001);

match book &123;
    Book::Papery &40;i&41; => {
        println!( "{}}", i&41;;
    },
    Book::Electronic &123; url &125; => {
        println!( "{}}", url&41;;
    }
}

In addition to being able to make branch selections for enum types, match can also be used for branch selection on integer, floating-point, character, and string slice references (&str) types. Although it is legal to use branch selection on floating-point types, it is not recommended because precision issues may lead to branch errors.

When making branch selections for non-enum types, it is necessary to handle exceptions, even if there is nothing to do in the case of exceptions. Exceptions are represented by an underscore _:

fn main() {
    let t = "abc";
    match t {
        "abc" => println!("Ja"),
        _ => {},
    }
}

Option-Enum-Klasse

Option ist eine Enum-Klasse in der Rust-Standardbibliothek, diese Klasse wird verwendet, um die Lücke von Rust, die keine null-Referenzen unterstützt, zu füllen.

Viele Sprachen unterstützen das Vorhandensein von null (C/C++、Java),das sehr praktisch ist, aber auch extreme Probleme verursacht, der Erfinder von null hat dies auch eingeräumt, "Eine praktische Idee hat zu einem Anstieg der 10 "Verluste in Milliardenhöhe".

null gibt oft Programmern die Möglichkeit, das Programm durch die Annahme, dass alles nicht null ist, zu töten: Schließlich führt ein solcher Fehler zum vollständigen Absturz des Programms.

Um dieses Problem zu lösen, verbieten viele Sprachen standardmäßig null, unterstützen aber die Erscheinung von null auf sprachlicher Ebene (oft durch den ?-Zeichen vor dem Typen gekennzeichnet).

Java unterstützt standardmäßig null, aber null kann durch die @NotNull-Annotation begrenzt werden, was eine Notlösung ist.

Rust verbietet das Vorhandensein von leeren Werten null auf sprachlicher Ebene, aber leider kann null effizient einige Probleme lösen, daher hat Rust die Enum-Klasse Option eingeführt:

enum Option<T> {
    Some(T),
    None,
}

Wenn du eine Klasse definieren möchtest, die leere Werte haben kann, kannst du das so tun:

let opt = Option::Some("Hallo");

Wenn du bestimmte Operationen für opt ausführen möchtest, musst du vorher überprüfen, ob er Option::None:

fn main() {
    let opt = Option::Some("Hallo");
    passen opt {
        Option::Some(etwas) => {
            println!("{}", etwas);
        },
        Option::None => {
            println!("opt ist nichts");
        }
    }
}

Laufender Output:

Hallo

Wenn dein Variable am Anfang leer ist, sei nachsichtig mit dem Compiler, wie soll er wissen, was der Typ der Variable ist, wenn der Wert nicht leer ist?

Daher muss eine leere Option eine klare Typbezeichnung haben:

fn main() {
    let opt: Option<&str> = Option::None;
    passen opt {
        Option::Some(etwas) => {
            println!("{}", etwas);
        },
        Option::None => {
            println!("opt ist nichts");
        }
    }
}

Laufender Output:

opt ist nichts

Diese Design-Variante macht es schwer, leere Werte zu programmieren, aber genau das ist erforderlich, um ein stabiles und effizientes System zu erstellen. Da Option Standardmäßig durch den Rust-Compiler eingeführt wird, kann man Option:: direkt schreiben None oder Some().

Option ist eine spezielle Enum-Klasse, die Wert-Auswahlzweige enthalten kann:

fn main() {
        let t = Some(64);
        match t {
                Some(64) => println!("Ja"),
                _ => println!("Nein"),
        }
}

if let-Syntax

let i = 0;
match i {
    0 => println!("zero"),
    _ => {},
}

Fügen Sie das Ergebnis in die Hauptfunktion ein:

zero

Das Ziel dieses Programms ist es zu bestimmen, ob i die Zahl 0 ist und falls ja, "zero" auszugeben.

Verwenden Sie die if let-Syntax, um diesen Code zu verkürzen:

let i = 0;
if let 0 = i {
    println!("zero");
}

Die Syntax der if let-Syntax ist wie folgt:

if let Wert = Quellvariable {
    Anweisungsblock
}

Es kann ein else-Block hinzugefügt werden, um Ausnahmen zu behandeln.

Die if let-Syntax kann als "Syntax-Süße" eines nur zwei Fälle unterscheidenden match-Statements betrachtet werden (Syntax-Süße ist ein bequemer Ersatz für eine Syntax mit demselben Prinzip).

Für Enum-Klassen gilt ebenfalls:

fn main() {
    enum Book {
        Papery(u32),
        Electronic(String)
    }
    let book = Book::Electronic(String::from("url"));
    if let Book::Papery(index) = book {
        println!("Papier {}", index);
    } else {
        println!("Nicht-papierbasiertes Buch");
    }
}