Objets de traits et dyn
Dispatch dynamique
Objets de traits et dyn est une leçon Learn Rust Coding gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Learn Rust Coding, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Learn Rust Coding comprend 4 leçons au total.
Le problème : des types mélangés
Les types génériques avec des contraintes de trait fonctionnent très bien lorsque chaque appel utilise un type concret unique. Mais que faire si vous voulez une collection de types différents qui partagent tous un trait ? Les génériques ne peuvent pas contenir un mélange de types.
Les objets de trait résolvent ce problème.
Qu’est-ce qu’un objet de trait ?
Un objet de trait est une valeur référencée par l’intermédiaire d’un pointeur et du mot-clé dyn, comme &dyn Trait ou Box<dyn Trait>.
Il vous permet de traiter uniformément plusieurs types concrets à l’exécution.
Une Box de dyn Trait
Box<dyn Trait> possède sur le tas une valeur d’un type qui implémente le trait. Vous appelez les méthodes du trait sans connaître le type concret.
trait Speak { fn say(&self) -> String; }
struct Dog;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
fn main() {
let animal: Box<dyn Speak> = Box::new(Dog);
println!("{}", animal.say());
}Un Vec d’objets de trait
L’avantage principal : un même vecteur peut contenir de nombreux types différents, à condition que chacun implémente le trait.
trait Speak { fn say(&self) -> String; }
struct Dog;
struct Cat;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
impl Speak for Cat { fn say(&self) -> String { String::from("Meow") } }
fn main() {
let zoo: Vec<Box<dyn Speak>> = vec![Box::new(Dog), Box::new(Cat)];
for animal in &zoo {
println!("{}", animal.say());
}
}Dispatch dynamique
Avec les objets de trait, la méthode à appeler est choisie à l’exécution en la recherchant dans une table cachée, la vtable. On appelle cela le dispatch dynamique.
Le coût est une petite indirection ; l’avantage est la flexibilité à l’exécution.
Fonctions renvoyant des objets de trait
Une fonction peut renvoyer Box<dyn Trait> lorsque le type concret varie. C’est utile pour les fonctions fabriques qui choisissent le type à l’exécution.
trait Speak { fn say(&self) -> String; }
struct Dog;
struct Cat;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
impl Speak for Cat { fn say(&self) -> String { String::from("Meow") } }
fn make(kind: &str) -> Box<dyn Speak> {
if kind == "dog" { Box::new(Dog) } else { Box::new(Cat) }
}
fn main() {
println!("{}", make("cat").say());
}Objets de trait empruntés
Vous pouvez également transmettre un objet de trait emprunté avec &dyn Trait lorsque vous n’avez pas besoin d’en posséder la valeur. Aucune allocation sur le tas n’est nécessaire.
trait Speak { fn say(&self) -> String; }
struct Dog;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
fn announce(s: &dyn Speak) {
println!("heard: {}", s.say());
}
fn main() {
let d = Dog;
announce(&d);
}Sûreté des objets
Tous les traits ne peuvent pas être utilisés comme objets de trait. Un trait doit être sûr pour les objets : en résumé, ses méthodes ne doivent pas renvoyer Self par valeur ni utiliser de paramètres de type génériques.
Les méthodes qui prennent &self et utilisent des types concrets conviennent.
Exemple non sûr pour les objets
Un trait dont une méthode renvoie Self ne peut pas être utilisé comme dyn, car la taille de Self est inconnue derrière un pointeur. Gardez les traits destinés aux objets simples.
Exemple de style système de modules d’extension
Les objets de trait sont particulièrement adaptés aux systèmes de modules d’extension : stockez une liste de gestionnaires derrière dyn et exécutez-les tous sans vous soucier des types concrets.
trait Task { fn run(&self) -> i32; }
struct Add { a: i32, b: i32 }
struct Negate { x: i32 }
impl Task for Add { fn run(&self) -> i32 { self.a + self.b } }
impl Task for Negate { fn run(&self) -> i32 { -self.x } }
fn main() {
let tasks: Vec<Box<dyn Task>> = vec![Box::new(Add { a: 2, b: 3 }), Box::new(Negate { x: 7 })];
let total: i32 = tasks.iter().map(|t| t.run()).sum();
println!("total {}", total);
}Quand utiliser dyn
Utilisez les objets de trait lorsque vous avez besoin de collections hétérogènes, de types choisis à l’exécution ou de réduire la taille du code généré par de nombreuses instanciations génériques.
Sinon, préférez les génériques pour obtenir une vitesse maximale.
Vérification rapide
Testez votre compréhension des objets de trait.
Récapitulatif
Vous avez appris le dispatch dynamique :
- Les objets de trait utilisent
dynderrière un pointeur (Box<dyn T>,&dyn T) - Ils permettent les collections hétérogènes et les types choisis à l’exécution
- Les appels de méthode passent par une vtable (dispatch dynamique)
- Les traits doivent être sûrs pour les objets pour être utilisés de cette manière
Questions Fréquemment Posées
La leçon « Objets de traits et dyn » est-elle gratuite ?
Oui — le texte complet de « Objets de traits et dyn » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Learn Rust Coding, passe à CoddyKit PRO. Le cours Learn Rust Coding comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Objets de traits et dyn » ?
Dispatch dynamique Tu pratiques Learn Rust Coding avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Learn Rust Coding ?
Aucune expérience préalable n'est requise. Learn Rust Coding sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Objets de traits et dyn » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Learn Rust Coding ?
Oui. Chaque leçon Learn Rust Coding inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Définition de traits
- Objets de traits et dyn
- Dispatch statique ou dynamique
- Méthodes par défaut