Menu
Coddy logo textTech

Das Option-Enum erneut betrachtet

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

Sie sind Option<T> bereits in Rust begegnet – es ist das Standard-Enum zur Darstellung von Werten, die existieren könnten oder auch nicht. Betrachten wir es nun aus einer OOP-Perspektive: Option ist nicht nur ein Enum, sondern ein Typ mit leistungsstarken integrierten Methoden, mit denen Sie Nullwerte sicher und elegant handhaben können.

Anstatt jedes Mal ein Matching durchzuführen, können Sie Methoden direkt auf Option-Werten verwenden. Die Methode unwrap_or gibt den inneren Wert zurück, falls dieser existiert, oder einen von Ihnen bereitgestellten 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 dieser existiert, und lässt None unverändert. Dies ermöglicht es Ihnen, Operationen zu 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 Option-Typ kapselt das Konzept von „vielleicht ein Wert“ und bietet eine saubere Schnittstelle für die Arbeit damit. Sie rufen Methoden auf dem Objekt auf, anstatt externe Logik zu schreiben, um es zu untersuchen.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Benutzerprofilsystem erstellen, das optionale Daten mithilfe von Option-Methoden elegant verarbeitet. Benutzer können einen Spitznamen festgelegt haben oder nicht – Ihr System wird beide Fälle elegant ohne explizites Matching handhaben.

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

  • profile.rs: Definieren Sie eine öffentliche Profile-Struktur mit zwei Feldern: username (String) und nickname (Option<String>). Implementieren Sie:
    • Einen new-Konstruktor, der einen Benutzernamen und einen optionalen Spitznamen entgegennimmt
    • Eine display_name-Methode, die den Spitznamen zurückgibt, falls er existiert, oder den Benutzernamen als Fallback – verwenden Sie unwrap_or, um dies zu handhaben
    • Eine formatted_nickname-Methode, die ein Option<String> zurückgibt, wobei der Spitzname in Klammern eingeschlossen ist (wie "[CoolNick]"), falls er existiert, oder None, falls kein Spitzname vorhanden ist – verwenden Sie map, um den Wert zu transformieren
  • main.rs: Binden Sie Ihr Profil-Modul ein und erstellen Sie zwei Profile – eines mit einem Spitznamen und eines ohne. Demonstrieren Sie beide Methoden an jedem Profil, um zu zeigen, wie Option-Methoden vorhandene und fehlende Werte unterschiedlich handhaben.

Verwenden Sie für die Methode formatted_nickname bei der Ausgabe die Debug-Formatierung ({:?}), da sie ein Option zurückgibt.

Ihre Ausgabe sollte genau diesem Format folgen und beide Profile zeigen:

Display name: {name}
Formatted nickname: {option}
Display name: {name}
Formatted nickname: {option}

Zum Beispiel wäre bei einem Profil für den Benutzernamen "alice" mit dem Spitznamen "Ace" und einem anderen für den Benutzernamen "bob" ohne Spitznamen die Ausgabe:

Display name: Ace
Formatted nickname: Some("[Ace]")
Display name: bob
Formatted nickname: None

Sie erhalten drei Eingaben: den ersten Benutzernamen, den Spitznamen des ersten Benutzers und den zweiten Benutzernamen (der keinen Spitznamen hat).

Spickzettel

Der Typ Option<T> bietet Methoden für die Arbeit mit optionalen Werten ohne explizites Matching.

Die Methode unwrap_or gibt den inneren Wert zurück, falls er existiert, oder einen Standardwert, falls er None ist:

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 Methode map transformiert den inneren Wert, falls er existiert, und lässt None unverändert:

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 ermöglichen das Verketten von Operationen auf Option-Werten, ohne ständig auf None prüfen zu müssen.

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: Ersten Profil mit username1 und nickname1 erstellen (Some)
    
    // TODO: Zweiten Profil mit username2 und ohne Spitznamen erstellen (None)
    
    // TODO: display_name und formatted_nickname für das erste Profil ausgeben
    // Verwende {:?} für formatted_nickname, da es eine Option zurückgibt
    
    // TODO: display_name und formatted_nickname für das zweite Profil 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