Section courante

A propos

Section administrative du site

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 :

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 :

  1. trait Zero {
  2.     const ZERO: Self;
  3.     fn is_zero(&self) -> bool;
  4. }
  5.  
  6. impl Zero for i32 {
  7.     const ZERO: Self = 0;
  8.  
  9.     fn is_zero(&self) -> bool {
  10.         *self == Self::ZERO
  11.     }
  12. }
  13.  
  14. assert_eq!(i32::ZERO, 0);
  15. assert!(i32::ZERO.is_zero());
  16. assert!(!4.is_zero());

Avec un type associé :

  1. trait Builder {
  2.     type Built;
  3.  
  4.     fn build(&self) -> Self::Built;
  5. }

Les traits peuvent être génériques, avec ou sans contraintes :

  1. trait MaybeFrom<T> {
  2.     fn maybe_from(value: T) -> Option<Self>
  3.     where
  4.         Self: Sized;
  5. }

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 :

  1. trait ThreeIterator: Iterator {
  2.     fn next_three(&mut self) -> Option<[Self::Item; 3]>;
  3. }

Les traits peuvent être utilisés dans les fonctions, comme paramètres :

  1. fn debug_iter<I: Iterator>(it: I) where I::Item: std::fmt::Debug {
  2.     for elem in it {
  3.         println!("{elem:#?}");
  4.     }
  5. }
  6.  
  7. // u8_len_1, u8_len_2 et u8_len_3 sont équivalents
  8.  
  9. fn u8_len_1(val: impl Into<Vec<u8>>) -> usize {
  10.     val.into().len()
  11. }
  12.  
  13. fn u8_len_2<T: Into<Vec<u8>>>(val: T) -> usize {
  14.     val.into().len()
  15. }
  16.  
  17. fn u8_len_3<T>(val: T) -> usize
  18. where
  19.     T: Into<Vec<u8>>,
  20. {
  21.     val.into().len()
  22. }

Ou comme types de retour :

  1. fn from_zero_to(v: u8) -> impl Iterator<Item = u8> {
  2.     (0..v).into_iter()
  3. }

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 :

  1. trait A {}
  2. trait B {}
  3.  
  4. let _: Box<dyn A + B>;

Ceci non plus, qui est une erreur de syntaxe :

  1. trait A {}
  2. trait B {}
  3.  
  4. let _: Box<dyn A + dyn B>;

D'un autre côté, c'est correct :

  1. trait A {}
  2.  
  3. let _: Box<dyn A + Send + Sync>;

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 :

  1. unsafe trait UnsafeTrait {}
  2.  
  3. unsafe impl UnsafeTrait for i32 {}

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 :

  1. trait Tr {
  2.     fn f(i32);
  3. }

Ce comportement n'est plus valable dans l'édition 2018.



Dernière mise à jour : Vendredi, le 1er Août 2025