Menu
Coddy logo textTech

Matching von Datenvarianten

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

In der vorherigen Lektion haben Sie match innerhalb von Enum-Methoden verwendet, um verschiedene Varianten zu behandeln. Konzentrieren wir uns nun darauf, wie match tatsächlich die in diesen Varianten gespeicherten Daten extrahiert – eine Technik, die als Destrukturierung bezeichnet wird.

Wenn du einen Abgleich auf eine Enum-Variante durchführst, die Daten enthält, kannst du diese Daten direkt im Muster an Variablen binden:

enum Event {
    Click { x: i32, y: i32 },
    KeyPress(char),
    Resize(u32, u32),
}

fn handle_event(event: Event) {
    match event {
        Event::Click { x, y } => {
            println!("Clicked at ({}, {})", x, y);
        }
        Event::KeyPress(key) => {
            println!("Key pressed: {}", key);
        }
        Event::Resize(width, height) => {
            println!("Resized to {}x{}", width, height);
        }
    }
}

Jeder Zweig extrahiert Daten unterschiedlich, basierend auf der Struktur der Variante. Für strukturähnliche Varianten verwenden Sie { field_name }, um benannte Felder zu extrahieren. Für Tupel-Varianten verwenden Sie Positionsvariablen wie (width, height).

Die von Ihnen gewählten Variablennamen werden innerhalb dieses Match-Arms verfügbar. Dies ist leistungsstark, da Sie gleichzeitig prüfen, welche Variante Sie haben, und Zugriff auf deren Payload erhalten.

Der Compiler stellt sicher, dass Sie jede Variante behandeln, und die extrahierten Werte sind sofort einsatzbereit – keine zusätzlichen Schritte erforderlich.

challenge icon

Aufgabe

Einfach

Lassen Sie uns einen Befehlsprozessor erstellen, der verschiedene Arten von Benutzerbefehlen verarbeitet. Jeder Befehl enthält unterschiedliche Daten, und Ihr Prozessor wird Pattern Matching verwenden, um diese Daten zu extrahieren und entsprechende Antworten zu erzeugen.

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

  • command.rs: Definieren Sie ein öffentliches Command-Enum mit drei Varianten:
    • Say — enthält eine einzelne String-Nachricht (Tupel-Syntax)
    • Move — enthält benannte Felder: direction (String) und steps (u32)
    • Calculate — enthält zwei i32-Werte, die zu addierende Zahlen darstellen (Tupel-Syntax)
    Implementieren Sie dann eine execute-Methode, die match verwendet, um jede Variante zu destrukturieren und einen String zurückzugeben, der die ausgeführte Aktion beschreibt.
  • main.rs: Binden Sie Ihr Befehlsmodul ein, erstellen Sie eine Instanz jeder Befehlsvariante unter Verwendung der bereitgestellten Eingaben und rufen Sie die execute-Methode für jede auf, um die Ergebnisse auszugeben.

Ihre execute-Methode sollte jede Variante destrukturieren, um auf ihre Daten zuzugreifen, und Nachrichten in genau diesen Formaten zurückgeben:

  • Für Say: Saying: {message}
  • Für Move: Moving {steps} steps {direction}
  • Für Calculate: {a} + {b} = {sum}

Ihre Ausgabe sollte das Ergebnis jedes Befehls in einer eigenen Zeile anzeigen:

Saying: {message}
Moving {steps} steps {direction}
{a} + {b} = {sum}

Zum Beispiel, mit einer Say-Nachricht von "Hello world", einer Bewegung von 5 Schritten nach "north" und einer Berechnung von 10 und 25, wäre die Ausgabe:

Saying: Hello world
Moving 5 steps north
10 + 25 = 35

Sie erhalten fünf Eingaben: die Say-Nachricht, die Richtung, die Anzahl der Schritte und die zwei zu berechnenden Zahlen.

Spickzettel

Pattern Matching mit match ermöglicht es Ihnen, Enum-Varianten zu destrukturieren und deren Daten direkt im Pattern zu extrahieren.

Für Tupel-Varianten verwenden Sie Positionsvariablen:

enum Event {
    KeyPress(char),
    Resize(u32, u32),
}

match event {
    Event::KeyPress(key) => {
        println!("Key: {}", key);
    }
    Event::Resize(width, height) => {
        println!("{}x{}", width, height);
    }
}

Für Struct-ähnliche Varianten verwenden Sie die Syntax für benannte Felder:

enum Event {
    Click { x: i32, y: i32 },
}

match event {
    Event::Click { x, y } => {
        println!("Clicked at ({}, {})", x, y);
    }
}

Die extrahierten Variablen werden innerhalb ihres jeweiligen Match-Arms verfügbar, sodass Sie gleichzeitig den Variantentyp prüfen und auf seine Daten zugreifen können.

Probier es selbst

mod command;

use command::Command;

fn main() {
    // Eingaben lesen
    let mut say_message = String::new();
    std::io::stdin().read_line(&mut say_message).expect("Failed to read line");
    let say_message = say_message.trim().to_string();

    let mut direction = String::new();
    std::io::stdin().read_line(&mut direction).expect("Failed to read line");
    let direction = direction.trim().to_string();

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

    let mut num1_input = String::new();
    std::io::stdin().read_line(&mut num1_input).expect("Failed to read line");
    let num1: i32 = num1_input.trim().parse().expect("Failed to parse num1");

    let mut num2_input = String::new();
    std::io::stdin().read_line(&mut num2_input).expect("Failed to read line");
    let num2: i32 = num2_input.trim().parse().expect("Failed to parse num2");

    // TODO: Erstelle einen Say-Befehl unter Verwendung von say_message und führe ihn aus
    
    // TODO: Erstelle einen Move-Befehl unter Verwendung von direction und steps und führe ihn aus
    
    // TODO: Erstelle einen Calculate-Befehl unter Verwendung von num1 und num2 und führe ihn aus
    
    // TODO: Gib die Ergebnisse jeder Befehlsausführung aus
}
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