Typ wyliczeniowy Option — powtórzenie
Część sekcji Programowanie obiektowe ścieżki Rust w Coddy. Lekcja 17 z 61.
W Rust spotkałeś już typ Option<T>: to standardowy typ wyliczeniowy reprezentujący wartości, które mogą istnieć lub nie. Teraz przyjrzyjmy się mu z perspektywy OOP: Option to nie tylko typ wyliczeniowy, ale także typ z zaawansowanymi wbudowanymi metodami, które pozwalają bezpiecznie i elegancko obsługiwać wartości nullowalne.
Zamiast za każdym razem dopasowywać, możesz używać metod bezpośrednio na wartościach Option. Metoda unwrap_or zwraca wartość wewnętrzną, jeśli istnieje, albo podaną przez ciebie wartość domyślną:
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
Metoda map przekształca wewnętrzną wartość, jeśli istnieje, pozostawiając None bez zmian. Dzięki temu możesz łączyć operacje bez ciągłego sprawdzania, czy występuje None:
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
Te metody ucieleśniają zasady programowania obiektowego: typ Option enkapsuluje pojęcie „może istnieć wartość” i zapewnia przejrzysty interfejs do pracy z nią. Wywołujesz metody na obiekcie, zamiast pisać zewnętrzną logikę, aby go sprawdzić.
Wyzwanie
ŁatwyZbudujmy system profili użytkowników, który elegancko obsługuje opcjonalne dane za pomocą metod Option. Użytkownicy mogą mieć ustawiony pseudonim albo nie. Twój system elegancko obsłuży oba przypadki bez jawnego dopasowywania.
Utworzysz dwa pliki, aby uporządkować kod:
profile.rs: Zdefiniuj publiczną strukturęProfilez dwoma polami:username(String) inickname(Option<String>). Zaimplementuj:- Konstruktor
new, który przyjmuje nazwę użytkownika i opcjonalny pseudonim - Metodę
display_name, która zwraca pseudonim, jeśli istnieje, a w przeciwnym razie nazwę użytkownika jako wartość zastępczą: użyjunwrap_or, aby to obsłużyć - Metodę
formatted_nickname, która zwracaOption<String>z pseudonimem ujętym w nawiasy (jak"[CoolNick]"), jeśli pseudonim istnieje, alboNone, jeśli go nie ma: użyjmap, aby przekształcić wartość
- Konstruktor
main.rs: Dołącz moduł profilu i utwórz dwa profile: jeden z pseudonimem, a drugi bez niego. Zademonstruj działanie obu metod dla każdego profilu, aby pokazać, jak metodyOptionobsługują różnie obecne i nieobecne wartości.
W metodzie formatted_nickname podczas drukowania użyj formatowania debug ({:?}), ponieważ zwraca ona Option.
Wynik powinien mieć dokładnie następujący format i pokazywać oba profile:
Display name: {name}
Formatted nickname: {option}
Display name: {name}
Formatted nickname: {option}Na przykład dla profilu o nazwie użytkownika "alice" i pseudonimie "Ace" oraz drugiego profilu o nazwie użytkownika "bob" bez pseudonimu wynik będzie następujący:
Display name: Ace
Formatted nickname: Some("[Ace]")
Display name: bob
Formatted nickname: NoneOtrzymasz trzy dane wejściowe: pierwszą nazwę użytkownika, pseudonim pierwszego użytkownika oraz drugą nazwę użytkownika (użytkownika bez pseudonimu).
REQUIRED OUTPUT FORMAT:Spróbuj swoich sił
mod profile;
use profile::Profile;
fn main() {
// Wczytaj dane wejściowe
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: Utwórz pierwszy profil z username1 i nickname1 (Some)
// TODO: Utwórz drugi profil z username2 i bez pseudonimu (None)
// TODO: Wypisz display_name i formatted_nickname dla pierwszego profilu
// Użyj {:?} dla formatted_nickname, ponieważ zwraca Option
// TODO: Wypisz display_name i formatted_nickname dla drugiego profilu
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Metody i zachowanie
Wprowadzenie do bloków implementacjiParametr selfMetody modyfikująceFunkcje powiązaneWiele bloków implementacjiŁańcuchowe wywoływanie metodPowtórzenie — działania na prostokącie4Projekt: Wirtualne zwierzątko
Definiowanie zwierzątkaKarmienie zwierzątka7Standardowe cechy
Cecha DebugCecha DisplayClone i CopyCechy równościPowtórka – punkt do wydrukowania10Projekt: System dokumentów
Trait DrawKomponent tekstowy2Hermetyzacja i moduły
Podstawy modułówSłowo kluczowe publicPola prywatneGetterySetteryPodsumowanie — bezpieczna skrytka5Typy generyczne
Struktury generyczneMetody generyczneWiele typów generycznychFunkcje generycznePodsumowanie – punkt współrzędnych8Cechy jako ograniczenia
Składnia ograniczeń cechWiele ograniczeńKlauzula whereZwracanie typów z użyciem cechPodsumowanie — generyczna drukarka11Wzorce projektowe w Rust
Wzorzec NewtypeKompozycjaTrait DropFrom i IntoPodsumowanie — atrapowy inteligentny wskaźnik3Zaawansowane typy wyliczeniowe
Typy wyliczeniowe z danymiMetody typów wyliczeniowychDopasowywanie wariantów danychTyp wyliczeniowy Option — powtórzeniePodsumowanie — typ wyliczeniowy Shape6Definiowanie cech
Czym jest cecha?Implementowanie cechImplementacje domyślneNadpisywanie wartości domyślnychCechy z parametramiPowtórzenie — odtwarzacz multimedialnyPoćwicz samodzielnie: Kompilator Rust online