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.
Aufgabe
EinfachLassen 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 öffentlichesTrafficLightEnum mit drei Varianten:Red— enthält einenu32, der die Sekunden zum Warten darstelltYellow— enthält einenu32, der die Sekunden zum Warten darstelltGreen— enthält einenu32, der die Sekunden zum Fahren darstellt
statusMethode, die einenStringzurückgibt, der die Ampel beschreibt. Verwenden Siematchinnerhalb 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 diestatusMethode 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} secondsZum 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 secondsSie 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
}
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
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