Das Option-Enum erneut betrachtet
Teil des Abschnitts Objektorientierte Programmierung der Rust-Journey von Coddy. Lektion 17 von 61.
Du bist in Rust bereits auf Option<T> gestoßen: Es ist das Standard-Enum zur Darstellung von Werten, die möglicherweise existieren oder auch nicht. Betrachten wir es nun aus der OOP-Perspektive: Option ist nicht nur ein Enum, sondern ein Typ mit leistungsstarken integrierten Methoden, mit denen du nullable Werte sicher und elegant behandeln kannst.
Statt jedes Mal zu matchen, kannst du Methoden direkt auf Option-Werten verwenden. Die Methode unwrap_or gibt den inneren Wert zurück, wenn er vorhanden ist, oder einen von dir angegebenen Standardwert:
let maybe_name: Option<String> = Some(String::from("Alice"));
let name = maybe_name.unwrap_or(String::from("Guest"));
println!("{}", name); // Alice
let empty: Option<String> = None;
let fallback = empty.unwrap_or(String::from("Guest"));
println!("{}", fallback); // Guest
Die map-Methode transformiert den inneren Wert, falls er exists, und lässt None unverändert. Dadurch kannst du Operationen verketten, ohne ständig auf None prüfen zu müssen:
let maybe_num: Option<i32> = Some(5);
let doubled = maybe_num.map(|x| x * 2);
println!("{:?}", doubled); // Some(10)
let nothing: Option<i32> = None;
let still_nothing = nothing.map(|x| x * 2);
println!("{:?}", still_nothing); // None
Diese Methoden verkörpern OOP-Prinzipien: Der Typ Option kapselt das Konzept „möglicherweise ein Wert“ und bietet eine klare Schnittstelle für die Arbeit damit. Du rufst Methoden für das Objekt auf, anstatt externe Logik zu schreiben, um es zu überprüfen.
Aufgabe
EinfachWir erstellen ein Benutzerprofilsystem, das optionale Daten mithilfe von Option-Methoden elegant verarbeitet. Benutzer können einen Spitznamen festgelegt haben oder auch nicht. Dein System wird beide Fälle elegant behandeln, ohne explizites Pattern Matching.
Du erstellst zwei Dateien, um deinen Code zu organisieren:
profile.rs: Definiere eine öffentlicheProfile-Struktur mit zwei Feldern:username(String) undnickname(Option<String>). Implementiere:- Einen
new-Konstruktor, der einen Benutzernamen und einen optionalen Spitznamen entgegennimmt - Eine
display_name-Methode, die den Spitznamen zurückgibt, wenn er vorhanden ist, oder als Ersatz den Benutzernamen: Verwendeunwrap_or, um dies zu behandeln - Eine
formatted_nickname-Methode, die einOption<String>mit dem in eckige Klammern eingeschlossenen Spitznamen (wie"[CoolNick]") zurückgibt, wenn er vorhanden ist, oderNone, wenn kein Spitzname vorhanden ist: Verwendemap, um den Wert umzuwandeln
- Einen
main.rs: Binde dein Profilmodul ein und erstelle zwei Profile: eines mit einem Spitznamen und eines ohne. Führe beide Methoden für jedes Profil vor, um zu zeigen, wieOption-Methoden vorhandene und fehlende Werte unterschiedlich behandeln.
Verwende für die formatted_nickname-Methode beim Ausgeben das Debug-Format ({:?}), da sie ein Option zurückgibt.
Deine Ausgabe sollte diesem exakten Format folgen und beide Profile anzeigen:
Display name: {name}
Formatted nickname: {option}
Display name: {name}
Formatted nickname: {option}Wenn du beispielsweise ein Profil für den Benutzernamen "alice" mit dem Spitznamen "Ace" und ein weiteres für den Benutzernamen "bob" ohne Spitznamen hast, würde die Ausgabe folgendermaßen aussehen:
Display name: Ace
Formatted nickname: Some("[Ace]")
Display name: bob
Formatted nickname: NoneDu erhältst drei Eingaben: den ersten Benutzernamen, den Spitznamen des ersten Benutzers und den zweiten Benutzernamen (der keinen Spitznamen hat).
Probier es selbst
mod profile;
use profile::Profile;
fn main() {
// Eingaben lesen
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let username1 = input1.trim().to_string();
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let nickname1 = input2.trim().to_string();
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let username2 = input3.trim().to_string();
// TODO: Erstelle das erste Profil mit username1 und nickname1 (Some)
// TODO: Create second profile with username2 and no nickname (None)
// TODO: Print display_name and formatted_nickname for first profile
// Use {:?} for formatted_nickname since it returns an Option
// TODO: Print display_name and formatted_nickname for second profile
}
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