Vincoli multipli
Fa parte della sezione Programmazione orientata agli oggetti del percorso Rust di Coddy. Lezione 41 di 61.
A volte un singolo vincolo di trait non basta. Potresti aver bisogno di un tipo generico che possa sia essere stampato sia fornire un riepilogo. Rust ti permette di richiedere più trait usando la sintassi +.
Ecco come specificare che un tipo deve implementare due trait:
use std::fmt::Display;
trait Summary {
fn summarize(&self) -> String;
}
fn announce<T: Display + Summary>(item: T) {
println!("Breaking news: {}", item);
println!("Summary: {}", item.summarize());
}
Il vincolo T: Display + Summary significa «T deve implementare sia Display sia Summary». All'interno della funzione, puoi usare le funzionalità di entrambi i trait: stampare con {} (da Display) e chiamare summarize() (da Summary).
Puoi concatenare tutti i trait che ti servono:
fn process<T: Display + Summary + Clone>(item: T) {
// Può stampare, riassumere E clonare
}
Questo schema è essenziale quando la tua funzione si basa su più comportamenti. Invece di accettare qualsiasi tipo e sperare che funzioni, dichiari esplicitamente quali capacità sono richieste e il compilatore le verifica in fase di compilazione.
Sfida
FacileCostruiamo un sistema di ispezione dei prodotti che richiede che gli articoli abbiano più capacità! Creerai una funzione generica che accetta solo tipi che implementano sia un trait personalizzato sia un trait standard, dimostrando come la sintassi + combina più vincoli.
Organizzerai il codice in due file:
product.rs: Definisci un trait pubblicoInspectablecon un metodo chiamatoinspectche accetta&selfe restituisce unaStringcontenente i dettagli dell'ispezione. Poi crea una struct pubblicaGadgetcon i campi pubbliciname(String) eserial(u32). Il tuo Gadget deve implementare siaInspectable(restituendoInspecting: {name}) siastd::fmt::Display(formattando come{name} (SN: {serial})). Infine, crea una funzione generica pubblica chiamatafull_reportche accetta qualsiasi tipoTche implementa siaDisplaysiaInspectable. Questa funzione deve stampare due righe: prima l'articolo usando il formattatore{}, poi il risultato della chiamata ainspect().main.rs: Importa il tuo modulo product e crea un'istanza diGadgetusando gli input forniti. Chiamafull_reportcon il tuo gadget per mostrare che soddisfa entrambi i requisiti dei trait.
Il vantaggio dei vincoli multipli è che la tua funzione full_report può usare le capacità di entrambi i trait, mostrando l'articolo in modo ordinato E ottenendo i dettagli dell'ispezione, il tutto garantito in fase di compilazione.
Il tuo output dovrebbe mostrare sia il formato di visualizzazione sia il risultato dell'ispezione:
{name} (SN: {serial})
Inspecting: {name}Per esempio, con gli input Smartwatch e 98765:
Smartwatch (SN: 98765)
Inspecting: SmartwatchRiceverai due input: il nome del gadget e il numero di serie (da analizzare come u32).
Provalo tu
mod product;
use product::{Gadget, full_report};
fn main() {
// Leggi i dati di input
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
let mut serial_input = String::new();
std::io::stdin().read_line(&mut serial_input).expect("Failed to read line");
let serial: u32 = serial_input.trim().parse().expect("Failed to parse serial");
// TODO: Crea un'istanza di Gadget con il nome e il numero di serie
// TODO: Chiama full_report con il tuo gadget
}
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