Lezioni del modulo (2/2)
Trait e Trait Bounds
I trait definiscono il comportamento che un tipo particolare possiede e può condividere con altri tipi. Possiamo usare i trait per definire un insieme di metodi che rappresentano una determinata funzionalità o interfaccia comune, in modo simile alle interfacce in altri linguaggi di programmazione.
I trait bounds (vincoli di trait) permettono di specificare che un tipo generico deve implementare un determinato trait, garantendo che i metodi richiesti siano disponibili a tempo di compilazione.
Definire e Implementare un Trait
Per definire un trait, usiamo la parola chiave trait seguita dalle firme dei metodi che i tipi dovranno implementare:
pub trait Summary {
fn summarize(&self) -> String;
}
Per implementare un trait su un tipo concreto, usiamo la sintassi impl TraitName for TypeName:
pub struct NewsArticle {
pub headline: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}", self.headline)
}
}
Trait Bounds (Vincoli di Trait)
Quando scriviamo funzioni generiche, possiamo vincolare i parametri di tipo per assicurarci che implementino uno specifico trait. La sintassi standard è <T: Trait>:
pub fn notify<T: Summary>(item: &T) {
println!("Notifica: {}", item.summarize());
}
In alternativa, per firme più complesse, possiamo usare la clausola where:
pub fn notify_advanced<T>(item: &T)
where
T: Summary
{
println!("Notifica: {}", item.summarize());
}
Prova tu
Esercizio 1: Il Trait Summary
Definisci un trait chiamato Summary contenente la firma del metodo fn summarize(&self) -> String;. Successivamente definisci una struct NewsArticle con un campo headline di tipo String ed implementa il trait Summary per essa in modo che il metodo summarize restituisca il valore del campo headline.
Mostra suggerimento
Definisci il trait `Summary`e la struct`NewsArticle`. Implementa con `impl Summary for NewsArticle`clonando il campo`self.headline.clone()`.
Soluzione disponibile dopo 3 tentativi
Esercizio 2: Trait Bounds con print_summary
Basandoti sul codice dell'esercizio precedente, definisci una funzione generica chiamata print_summary<T> che accetta un parametro item di tipo &T. Applica un vincolo (trait bound) in modo che T debba implementare il trait Summary. All'interno della funzione, stampa a schermo il risultato restituito da item.summarize().
Mostra suggerimento
Usa la firma `fn print_summary<T: Summary>(item: &T)`ed invoca`item.summarize()`all'interno del`println!`.
Soluzione disponibile dopo 3 tentativi
Esercizio 3: Calcolo dell'Area tramite Trait
Definisci un trait chiamato Area con il metodo fn area(&self) -> f64;. Crea una struct Circle contenente un campo radius di tipo f64, ed implementa il trait Area per essa calcolando l'area (formula: radius * radius * 3.14159).
Mostra suggerimento
Definisci il trait `Area`e la struct`Circle`. Implementa `area(&self)` usando la formula del cerchio.
Soluzione disponibile dopo 3 tentativi