Enums mit Daten
Teil des Abschnitts Objektorientierte Programmierung der Rust-Journey von Coddy. Lektion 14 von 61.
Mit grundlegenden Enums in Rust kannst du einen Typ mit einer festen Menge von Varianten definieren, etwa Direction::North oder Status::Active. Rust-Enums sind jedoch weitaus leistungsfähiger. Jede Variante kann ihre eigenen Daten enthalten, wodurch Enums unglaublich flexibel für die Modellierung realer Szenarien werden.
Stell dir ein Nachrichtensystem vor, in dem verschiedene Nachrichtentypen unterschiedliche Informationen enthalten. Eine Textnachricht hat einen Inhalt, ein Bewegungsbefehl hat Koordinaten und ein Beendigungssignal hat überhaupt keine Informationen. In Rust kannst du all dies mit einem einzigen Enum darstellen:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
Jede Variante hat eine andere Form. Quit enthält keine Daten: Es ist einfach ein Signal.
Move verwendet eine strukturähnliche Syntax mit benannten Feldern. Write enthält einen einzelnen String mithilfe der Tupelsyntax. ChangeColor enthält drei Werte, die RGB-Komponenten darstellen.
Das Erstellen von Instanzen dieser Varianten sieht so aus:
let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("Hello"));
let m4 = Message::ChangeColor(255, 128, 0);
Das Schöne an diesem Ansatz ist, dass m1, m2, m3 und m4 alle denselben Typ haben: Message. Du kannst sie in derselben Sammlung speichern, an dieselbe Funktion übergeben oder jede Variante aus einer einzelnen Funktion zurückgeben. Das Enum vereint unterschiedliche Datenformen unter einem Typ und bewahrt dabei die spezifischen Informationen, die jede Variante benötigt.
Aufgabe
EinfachErstellen wir ein Benachrichtigungssystem, das Enums mit Daten verwendet, um verschiedene Arten von Alarmen darzustellen. Jeder Benachrichtigungstyp enthält unterschiedliche Informationen: Einige enthalten Nachrichten, einige numerische Werte und einige sind einfache Signale.
Du wirst zwei Dateien erstellen, um deinen Code zu organisieren:
notification.rs: Definiere ein öffentlichesNotification-Enum mit drei Varianten:Alert: enthält eine einzelneString-Nachricht (Tupel-Syntax)Reminder: enthält benannte Felder:title(String) undminutes(u32)Dismiss: enthält keine Daten, sondern nur ein Signal
main.rs: Binde dein Benachrichtigungsmodul ein und erstelle eine Instanz jeder Variante. Gib anschließend Informationen zu jeder Benachrichtigung aus, um zu zeigen, dass alle drei Varianten denselben Typ haben, aber unterschiedliche Daten enthalten.
Verwende beim Ausgeben das Debug-Format ({:?}), um jede Benachrichtigung anzuzeigen. Du musst das Debug-Trait für dein Enum ableiten, damit es auf diese Weise ausgegeben werden kann.
Deine Ausgabe sollte alle drei Benachrichtigungen anzeigen, jede in einer eigenen Zeile:
Alert("{message}")
Reminder { title: "{title}", minutes: {minutes} }
DismissWenn die Alert-Nachricht beispielsweise "Server down" lautet, der Titel der Erinnerung "Meeting" ist und sie 30 Minuten beträgt, würde die Ausgabe folgendermaßen aussehen:
Alert("Server down")
Reminder { title: "Meeting", minutes: 30 }
DismissDu erhältst drei Eingaben: die Alert-Nachricht, den Titel der Erinnerung und die Erinnerungsdauer in Minuten.
Probier es selbst
mod notification;
use notification::Notification;
fn main() {
// Eingaben lesen
let mut alert_message = String::new();
std::io::stdin().read_line(&mut alert_message).expect("Failed to read line");
let alert_message = alert_message.trim().to_string();
let mut reminder_title = String::new();
std::io::stdin().read_line(&mut reminder_title).expect("Failed to read line");
let reminder_title = reminder_title.trim().to_string();
let mut minutes_input = String::new();
std::io::stdin().read_line(&mut minutes_input).expect("Failed to read line");
let reminder_minutes: u32 = minutes_input.trim().parse().expect("Failed to parse minutes");
// TODO: Erstelle eine Alert-Benachrichtigung mit der alert_message
// TODO: Create a Reminder notification using reminder_title and reminder_minutes
// TODO: Erstelle eine Dismiss-Benachrichtigung
// TODO: Gib jede Benachrichtigung mit Debug-Formatierung {:?} aus
// Jede Benachrichtigung sollte in einer eigenen Zeile ausgegeben werden
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Methoden und Verhalten
Einführung in ImplementierungsblöckeDer Self-ParameterVeränderliche MethodenAssoziierte FunktionenMehrere ImplementierungsblöckeMethod ChainingRückblick – Rechteck-Aktionen4Projekt: Virtuelles Haustier
Das Haustier definierenDas Haustier füttern7Standard-Traits
Das Debug-TraitDas Display-TraitClone und CopyGleichheits-TraitsZusammenfassung – Druckbarer Punkt10Projekt: Dokumentensystem
Das Draw-TraitText-Komponente2Kapselung und Module
Grundlagen der ModuleDas Public-SchlüsselwortPrivate FelderGetterSetterWiederholung – Sicherer Tresor5Generics
Generische StructsGenerische MethodenMehrere generische TypenGenerische FunktionenZusammenfassung - Koordinatenpunkt8Traits als Einschränkungen
Syntax für Trait BoundsMehrfache BoundsDie Where-KlauselTypen mit Traits zurückgebenRückblick – Generischer Drucker11Design Patterns in Rust
Newtype-PatternKompositionDas Drop-TraitFrom und IntoZusammenfassung – Smart Pointer Mock3Fortgeschrittene Enums
Enums mit DatenMethoden für EnumsMatching von DatenvariantenDas Option-Enum erneut betrachtetZusammenfassung – Shape-Enum6Definition von Traits
Was ist ein Trait?Traits implementierenStandardimplementierungenStandardimplementierungen überschreibenTraits mit ParameternZusammenfassung – Media PlayerÜbe selbstständig: Online-Rust-Compiler