Dispatch statico e dinamico
Compromessi
Dispatch statico e dinamico è una lezione Learn Rust Coding gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Learn Rust Coding, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Learn Rust Coding include 4 lezioni in totale.
Due modi per effettuare il dispatch
Quando si chiama un metodo di un trait, Rust deve decidere quale implementazione concreta eseguire. Esistono due strategie: il dispatch statico (deciso in fase di compilazione) e il dispatch dinamico (deciso in fase di esecuzione).
Dispatch statico con i generics
Le funzioni generiche usano il dispatch statico. Il compilatore genera una copia specializzata per ogni tipo concreto: un processo chiamato monomorfizzazione.
trait Area { fn area(&self) -> f64; }
struct Square { s: f64 }
impl Area for Square { fn area(&self) -> f64 { self.s * self.s } }
fn print_area<T: Area>(shape: &T) {
println!("{}", shape.area());
}
fn main() {
print_area(&Square { s: 4.0 });
}Monomorfizzazione
Per ogni tipo con cui si chiama la funzione, il compilatore crea una versione dedicata. La chiamata al metodo diventa una chiamata diretta senza ricerca, quindi è veloce quanto il codice scritto a mano.
Dispatch dinamico con dyn
Gli oggetti trait usano il dispatch dinamico. Una sola funzione gestisce tutti i tipi; l'indirizzo del metodo viene individuato in fase di esecuzione tramite una vtable.
trait Area { fn area(&self) -> f64; }
struct Square { s: f64 }
impl Area for Square { fn area(&self) -> f64 { self.s * self.s } }
fn print_area(shape: &dyn Area) {
println!("{}", shape.area());
}
fn main() {
print_area(&Square { s: 4.0 });
}La vtable
Un oggetto trait è un puntatore fat: una parte punta ai dati, l'altra a una vtable che elenca gli indirizzi dei metodi. Ogni chiamata utilizza un indice in questa tabella.
Questa indirezione aggiuntiva è il costo in fase di esecuzione.
Compromesso sulle prestazioni
Il dispatch statico è più veloce per chiamata e può essere sottoposto a inlining, ma genera più codice macchina. Il dispatch dinamico aggiunge una piccola indirezione, ma mantiene ridotte le dimensioni del codice.
Per la maggior parte delle app la differenza è trascurabile; scelga in base alla flessibilità.
Compromesso sulle dimensioni del codice
Chiamare una funzione generica con molti tipi crea molte copie, che possono gonfiare il binario. Una singola funzione dyn evita questa duplicazione.
Per questo le librerie a volte preferiscono usare internamente gli oggetti trait.
Compromesso sulla flessibilità
I generics impongono un tipo concreto per ogni punto di chiamata, quindi non possono contenere tipi diversi in una raccolta. Gli oggetti trait possono farlo. Se serve un elenco eterogeneo, la risposta è il dispatch dinamico.
trait Area { fn area(&self) -> f64; }
struct Square { s: f64 }
struct Rect { w: f64, h: f64 }
impl Area for Square { fn area(&self) -> f64 { self.s * self.s } }
impl Area for Rect { fn area(&self) -> f64 { self.w * self.h } }
fn main() {
let shapes: Vec<Box<dyn Area>> = vec![Box::new(Square { s: 2.0 }), Box::new(Rect { w: 3.0, h: 4.0 })];
let total: f64 = shapes.iter().map(|s| s.area()).sum();
println!("{}", total);
}Usare entrambi
È possibile combinarli: una funzione generica può accettare impl Trait all'interfaccia e memorizzare internamente i valori come Box<dyn Trait>. Usi ciascun approccio dove è più adatto.
Una guida alla scelta
Regole rapide:
- Un tipo per chiamata, percorso critico? Usi i generics (statico).
- Tipi diversi in una raccolta? Usi
dyn(dinamico). - La dimensione del binario è una preoccupazione? Preferisca
dyn.
Entrambi hanno costo zero dove conta
Rust non aggiunge overhead che non sia stato richiesto. I generics non hanno alcun costo in fase di esecuzione; gli oggetti trait costano solo un'indirezione tramite puntatore. Il compromesso viene scelto esplicitamente.
Verifica rapida
Metta alla prova le sue conoscenze sul dispatch.
Riepilogo
Ha confrontato i due stili di dispatch:
- Statico (generics): monomorfizzato, veloce, binario più grande, un tipo per chiamata
- Dinamico (
dyn): ricerca nella vtable, flessibile, codice più piccolo, consente raccolte con tipi diversi - Scelga in base alle esigenze di flessibilità, prestazioni e dimensioni del binario
Domande Frequenti
La lezione «Dispatch statico e dinamico» è gratuita?
Sì — il testo completo di «Dispatch statico e dinamico» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Learn Rust Coding, passa a CoddyKit PRO. Il corso Learn Rust Coding include 4 lezioni in totale.
Cosa imparerò in «Dispatch statico e dinamico»?
Compromessi Eserciti Learn Rust Coding con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Learn Rust Coding?
Non è richiesta alcuna esperienza precedente. Learn Rust Coding su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Dispatch statico e dinamico»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Learn Rust Coding?
Sì. Ogni lezione Learn Rust Coding include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Definizione dei trait
- Trait object e dyn
- Dispatch statico e dinamico
- Metodi predefiniti