Menu
Coddy logo textTech

Enums mit Daten

Teil des Abschnitts Object Oriented Programming der Rust-Journey von Coddy — Lektion 14 von 61.

Basis-Enums in Rust ermöglichen es Ihnen, einen Typ mit einer festen Menge an Varianten zu definieren—wie Direction::North oder Status::Active. Aber Rust-Enums sind weitaus mächtiger als das. Jede Variante kann ihre eigenen Daten enthalten, was Enums unglaublich flexibel für die Modellierung von realen Szenarien macht.

Stellen Sie sich ein Messaging-System vor, bei dem verschiedene Nachrichtentypen unterschiedliche Informationen enthalten. Eine Textnachricht hat einen Inhalt, ein Verschiebungsbefehl hat Koordinaten und ein Beendigungssignal hat gar nichts. In Rust können Sie 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 nur ein Signal.

Move verwendet eine Struct-ähnliche Syntax mit benannten Feldern. Write enthält einen einzelnen String unter Verwendung der Tupel-Syntax. 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 vom gleichen Typ sind: Message. Sie können sie in derselben Sammlung speichern, sie an dieselbe Funktion übergeben oder jede beliebige Variante von einer einzelnen Funktion zurückgeben. Das Enum vereinheitlicht verschiedene Datenformen unter einem Typ, während die spezifischen Informationen, die jede Variante benötigt, erhalten bleiben.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Benachrichtigungssystem bauen, das Enums mit Daten verwendet, um verschiedene Arten von Alarmen darzustellen. Jeder Benachrichtigungstyp trägt unterschiedliche Informationen — einige haben Nachrichten, einige haben numerische Werte und einige sind einfache Signale.

Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:

  • notification.rs: Definieren Sie ein öffentliches Notification Enum mit drei Varianten:
    • Alert — enthält eine einzelne String Nachricht (Tupel-Syntax)
    • Reminder — enthält benannte Felder: title (String) und minutes (u32)
    • Dismiss — enthält keine Daten, nur ein Signal
  • main.rs: Binden Sie Ihr Benachrichtigungsmodul ein und erstellen Sie eine Instanz jeder Variante. Geben Sie dann Informationen über jede Benachrichtigung aus, um zu demonstrieren, dass alle drei Varianten vom gleichen Typ sind, aber unterschiedliche Daten tragen.

Verwenden Sie beim Drucken die Debug-Formatierung ({:?}), um jede Benachrichtigung anzuzeigen. Sie müssen das Debug-Trait für Ihr Enum ableiten (derive), damit es auf diese Weise gedruckt werden kann.

Ihre Ausgabe sollte alle drei Benachrichtigungen zeigen, jede in einer eigenen Zeile:

Alert("{message}")
Reminder { title: "{title}", minutes: {minutes} }
Dismiss

Zum Beispiel, mit einer Alert-Nachricht "Server down", einem Reminder mit dem Titel "Meeting" und 30 Minuten, wäre die Ausgabe:

Alert("Server down")
Reminder { title: "Meeting", minutes: 30 }
Dismiss

Sie erhalten drei Eingaben: die Alert-Nachricht, den Reminder-Titel und die Reminder-Minuten.

Spickzettel

Enum-Varianten in Rust können verschiedene Datentypen enthalten, was sie zu einem mächtigen Werkzeug für die Modellierung unterschiedlicher Szenarien unter einem einzigen Typ macht.

Enums mit Daten definieren

Jede Variante kann ihre eigene Datenstruktur haben:

enum Message {
    Quit,                          // Keine Daten
    Move { x: i32, y: i32 },      // Benannte Felder (Struct-ähnlich)
    Write(String),                 // Einzelner Wert (Tupel-Syntax)
    ChangeColor(u8, u8, u8),      // Mehrere Werte (Tupel-Syntax)
}

Enum-Instanzen erstellen

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);

Alle Instanzen haben denselben Typ (Message), obwohl sie unterschiedliche Daten enthalten. Dies ermöglicht es, sie einheitlich in Sammlungen zu speichern, an Funktionen zu übergeben oder von Funktionen zurückzugeben.

Debug-Trait

Um Enums mit der Formatierung {:?} auszugeben, leiten Sie den Debug-Trait ab:

#[derive(Debug)]
enum Message {
    // Varianten...
}

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: Erstelle eine Reminder-Benachrichtigung mit reminder_title und reminder_minutes

    // TODO: Erstelle eine Dismiss-Benachrichtigung

    // TODO: Gib jede Benachrichtigung mit Debug-Formatierung {:?} aus
    // Jede Benachrichtigung sollte in einer eigenen Zeile ausgegeben werden
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Object Oriented Programming