trait |
Trait |
|---|---|
| Rust | |
Syntaxe
|
trait NomDuTrait { fn nom_methode(&self); } |
Paramètres
| Nom | Description |
|---|---|
| NomDuTrait | Ce paramètre permet de nommer le trait, facilitant sa réutilisation et son implémentation dans d'autres types. |
| fn nom_methode(&self); | Ce paramètre permet de déclarer une méthode que tout type implémentant le trait devra définir. |
Description
Ce mot réservé permet de définir un trait.
Remarques
Une interface commune à un groupe de types.
Un trait est comme une interface implémentable par des types de données. Lorsqu'un type implémente un trait, il peut être traité de manière abstraite comme ce trait à l'aide de génériques ou d'objets trait.
Les traits peuvent être composés de trois types d'éléments associés :
- fonctions et méthodes
- types
- constantes
Les traits peuvent également contenir des paramètres de type supplémentaires. Ces paramètres, ou le trait lui-même, peuvent être contraints par d'autres traits.
Les traits peuvent servir de marqueurs ou véhiculer une sémantique logique autre que leurs éléments. Lorsqu'un type implémente ce trait, il promet de respecter son contrat. Send et Sync sont deux de ces traits marqueurs présents dans la bibliothèque standard.
Exemples
Les traits sont déclarés à l'aide du mot clef trait. Les types peuvent les implémenter à l'aide de impl Trait pour Type :
Avec un type associé :
Les traits peuvent être génériques, avec ou sans contraintes :
Les traits peuvent s'appuyer sur les exigences d'autres traits. Dans l'exemple ci-dessous, Iterator est un supertrait et ThreeIterator un sous-trait :
Les traits peuvent être utilisés dans les fonctions, comme paramètres :
- fn debug_iter<I: Iterator>(it: I) where I::Item: std::fmt::Debug {
- for elem in it {
- println!("{elem:#?}");
- }
- }
-
- // u8_len_1, u8_len_2 et u8_len_3 sont équivalents
-
- fn u8_len_1(val: impl Into<Vec<u8>>) -> usize {
- val.into().len()
- }
-
- fn u8_len_2<T: Into<Vec<u8>>>(val: T) -> usize {
- val.into().len()
- }
-
- fn u8_len_3<T>(val: T) -> usize
- where
- T: Into<Vec<u8>>,
- {
- val.into().len()
- }
Ou comme types de retour :
L'utilisation du mot clef impl à cet endroit permet au développeur de la fonction de masquer le type concret comme un détail d'implémentation modifiable sans endommager le code utilisateur.
Objets trait
Un objet trait est une valeur opaque d'un autre type implémentant un ensemble de traits. Un objet trait implémente tous les traits spécifiés, ainsi que leurs super-traits (le cas échéant).
La syntaxe est la suivante : dyn BaseTrait + AutoTrait1 + ... AutoTraitN. Un seul BaseTrait peut être utilisé, la compilation échoue donc :
Ceci non plus, qui est une erreur de syntaxe :
D'un autre côté, c'est correct :
Traits non sécurisés
Certains traits peuvent être implémentés de manière non sécurisée. L'utilisation du mot clef unsafe devant la déclaration du trait permet de le signaler :
Différences entre les éditions 2015 et 2018
Dans l'édition 2015, le modèle de paramètres n'était pas nécessaire pour les traits :
Ce comportement n'est plus valable dans l'édition 2018.