L'enumerazione Option ripresa
Fa parte della sezione Programmazione orientata agli oggetti del percorso Rust di Coddy. Lezione 17 di 61.
Hai già incontrato Option<T> in Rust: è l'enum standard per rappresentare valori che potrebbero esistere oppure no. Ora esaminiamolo da una prospettiva OOP: Option non è solo un enum, è un tipo con potenti metodi integrati che ti consentono di gestire valori nullabili in modo sicuro ed elegante.
Invece di usare un’espressione di corrispondenza ogni volta, puoi usare metodi direttamente sui valori di Option. Il metodo unwrap_or restituisce il valore interno, se esiste, oppure un valore predefinito che fornisci:
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
Il metodo map trasforma il valore interno se esiste, lasciando None invariato. Questo ti consente di concatenare operazioni senza controllare continuamente 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
Questi metodi incarnano i principi della programmazione orientata agli oggetti (OOP): il tipo Option racchiude il concetto di «forse un valore» e fornisce un’interfaccia semplice per lavorarci. Chiami i metodi sull’oggetto invece di scrivere una logica esterna per esaminarlo.
Sfida
FacileCreiamo un sistema di profili utente che gestisca con eleganza i dati facoltativi usando i metodi di Option. Gli utenti potrebbero avere un nickname impostato oppure no. Il tuo sistema gestirà elegantemente entrambi i casi senza confronti espliciti.
Creerai due file per organizzare il codice:
profile.rs: definisci una struct pubblicaProfilecon due campi:username(String) enickname(Option<String>). Implementa:- Un costruttore
newche accetta uno username e un nickname facoltativo - Un metodo
display_nameche restituisce il nickname se esiste, oppure lo username come valore predefinito: usaunwrap_orper gestire questo caso - Un metodo
formatted_nicknameche restituisce unOption<String>con il nickname racchiuso tra parentesi quadre (come"[CoolNick]") se esiste, oppureNonese non c'è alcun nickname: usamapper trasformare il valore
- Un costruttore
main.rs: importa il modulo del profilo e crea due profili: uno con un nickname e uno senza. Mostra entrambi i metodi per ciascun profilo per illustrare come i metodi diOptiongestiscono diversamente i valori presenti e assenti.
Per il metodo formatted_nickname, usa la formattazione di debug ({:?}) durante la stampa, perché restituisce un Option.
L'output deve seguire questo formato esatto e mostrare entrambi i profili:
Display name: {name}
Formatted nickname: {option}
Display name: {name}
Formatted nickname: {option}Per esempio, con un profilo per lo username "alice" con nickname "Ace" e un altro per lo username "bob" senza nickname, l'output sarebbe:
Display name: Ace
Formatted nickname: Some("[Ace]")
Display name: bob
Formatted nickname: NoneRiceverai tre input: il primo username, il nickname del primo utente e il secondo username (che non ha un nickname).
Provalo tu
mod profile;
use profile::Profile;
fn main() {
// Leggi gli input
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: Crea il primo profilo con username1 e nickname1 (Some)
// TODO: Crea il secondo profilo con username2 e senza soprannome (None)
// TODO: Stampa display_name e formatted_nickname per il primo profilo
// Usa {:?} per formatted_nickname, poiché restituisce un Option
// TODO: Stampa display_name e formatted_nickname per il secondo profilo
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Metodi e comportamento
Introduzione ai blocchi implIl parametro selfMetodi mutabiliFunzioni associateBlocchi impl multipliConcatenamento di metodiRiepilogo - Azioni sul rettangolo4Progetto: animale domestico virtuale
Definire l'animaleNutrire l'animale7Trait standard
Il trait DebugIl trait DisplayClone e CopyTrait di uguaglianzaRiepilogo - Punto stampabile10Progetto: sistema di documenti
Il trait DrawComponente di testo2Incapsulamento e moduli
Nozioni di base sui moduliLa parola chiave publicCampi privatiGetterSetterRiepilogo - Armadietto sicuro5Generics
Struct genericheMetodi genericiPiù tipi genericiFunzioni genericheRipasso - Punto di coordinate8I Trait come vincoli
Sintassi dei vincoli sui traitVincoli multipliLa clausola whereRestituire tipi con i traitRiepilogo - Stampante generica11Modelli di progettazione in Rust
Pattern NewtypeComposizioneIl trait DropFrom e IntoRipasso - Mock con smart pointer3Enumerazioni avanzate
Enumerazioni con datiMetodi sulle enumerazioniCorrispondenza delle varianti con datiL'enumerazione Option ripresaRiepilogo - enumerazione Shape6Definizione dei trait
Che cos’è un trait?Implementare i traitImplementazioni predefiniteSovrascrivere le implementazioni predefiniteTrait con parametriRiepilogo - Lettore multimedialeEsercitati da solo: Compilatore Rust online