Menu
Coddy logo textTech

Methoden für Enums

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

Genau wie Structs können Enums Methoden haben, die in impl-Blöcken definiert sind. Dies ermöglicht es Ihnen, Verhalten direkt an Ihren Enum-Typ zu binden, was die Arbeit mit verschiedenen Varianten über eine einheitliche Schnittstelle erleichtert.

So fügen Sie eine Methode zum Message Enum aus der vorherigen Lektion hinzu:

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
}

impl Message {
    fn describe(&self) -> String {
        match self {
            Message::Quit => String::from("Quit signal"),
            Message::Move { x, y } => format!("Move to ({}, {})", x, y),
            Message::Write(text) => format!("Message: {}", text),
        }
    }
}

Der impl Message-Block funktioniert genau so, wie er es für Structs tut. Die Methode nimmt &self entgegen, um auf die Enum-Instanz zuzugreifen. Innerhalb der Methode verwenden Sie match, um festzustellen, mit welcher Variante Sie es zu tun haben, und geben das entsprechende Ergebnis zurück.

Der Aufruf der Methode sieht gleich aus, unabhängig davon, welche Variante vorliegt:

fn main() {
    let m1 = Message::Quit;
    let m2 = Message::Move { x: 10, y: 20 };
    
    println!("{}", m1.describe());  // Beenden-Signal
    println!("{}", m2.describe());  // Bewegen nach (10, 20)
}

Dieses Pattern ist sehr leistungsfähig, da der Aufrufer nicht wissen muss, welche Variante er hat – er ruft einfach die Methode auf, und das Enum erledigt den Rest intern. Das Verhalten ändert sich basierend auf der Variante, aber das Interface bleibt konsistent.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Ampelsystem bauen, das ein Enum mit Methoden verwendet, um den aktuellen Signalzustand zu beschreiben. Jede Lichtfarbe enthält Informationen darüber, wie lange sie dauert, und eine Methode liefert eine menschenlesbare Beschreibung.

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

  • traffic.rs: Definieren Sie ein öffentliches TrafficLight Enum mit drei Varianten:
    • Red — enthält einen u32, der die Sekunden zum Warten darstellt
    • Yellow — enthält einen u32, der die Sekunden zum Warten darstellt
    • Green — enthält einen u32, der die Sekunden zum Fahren darstellt
    Implementieren Sie dann eine status Methode, die einen String zurückgibt, der die Ampel beschreibt. Verwenden Sie match innerhalb der Methode, um jede Variante zu behandeln und die Dauer in die Nachricht einzufügen.
  • main.rs: Binden Sie Ihr Traffic-Modul ein, erstellen Sie Instanzen jeder Ampelvariante und rufen Sie die status Methode für jede auf, um die Beschreibungen auszugeben.

Die status Methode sollte Nachrichten in genau diesen Formaten zurückgeben:

  • Für Red: Stop for {seconds} seconds
  • Für Yellow: Caution for {seconds} seconds
  • Für Green: Go for {seconds} seconds

Ihre Ausgabe sollte den Status jeder Ampel in einer eigenen Zeile anzeigen:

Stop for {seconds} seconds
Caution for {seconds} seconds
Go for {seconds} seconds

Zum Beispiel wäre bei einer roten Ampel von 30 Sekunden, einer gelben von 5 Sekunden und einer grünen von 25 Sekunden die Ausgabe:

Stop for 30 seconds
Caution for 5 seconds
Go for 25 seconds

Sie erhalten drei Eingaben: die Dauer der roten Ampel, die Dauer der gelben Ampel und die Dauer der grünen Ampel.

Spickzettel

Enums können Methoden in impl-Blöcken definiert haben, genau wie Structs:

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
}

impl Message {
    fn describe(&self) -> String {
        match self {
            Message::Quit => String::from("Quit signal"),
            Message::Move { x, y } => format!("Move to ({}, {})", x, y),
            Message::Write(text) => format!("Message: {}", text),
        }
    }
}

Methoden nehmen &self, um auf die Enum-Instanz zuzugreifen, und verwenden match, um verschiedene Varianten zu behandeln:

let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };

println!("{}", m1.describe());  // Beenden-Signal
println!("{}", m2.describe());  // Bewegen nach (10, 20)

Der Aufrufer verwendet dieselbe Schnittstelle, unabhängig von der Variante – das Enum verarbeitet das Verhalten intern basierend darauf, um welche Variante es sich handelt.

Probier es selbst

mod traffic;

use traffic::TrafficLight;

fn main() {
    // Eingabe für die Zeitdauern lesen
    let mut red_input = String::new();
    std::io::stdin().read_line(&mut red_input).expect("Failed to read line");
    let red_duration: u32 = red_input.trim().parse().expect("Invalid number");

    let mut yellow_input = String::new();
    std::io::stdin().read_line(&mut yellow_input).expect("Failed to read line");
    let yellow_duration: u32 = yellow_input.trim().parse().expect("Invalid number");

    let mut green_input = String::new();
    std::io::stdin().read_line(&mut green_input).expect("Failed to read line");
    let green_duration: u32 = green_input.trim().parse().expect("Invalid number");

    // TODO: Instanzen jeder TrafficLight-Variante mit den eingegebenen Zeitdauern erstellen

    // TODO: Die status-Methode für jede Ampel aufrufen und das Ergebnis ausgeben
}
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