Alors, ce n’est pas étonnant que tu aies du mal à comprendre, parce que les traits de Rust sont en fait un concept qui vient de la programmation fonctionnelle : habituellement, on appelle cela des classes de types (et non, ça n’a pas grand chose à voir avec les classes de la programmation orientée objet (oui, c’est casse-bonbons )).
Les langages fonctionnels, et le Rust, ne permettent pas la surcharge de fonctions et d’opérateurs comme on peut le faire en C++. À la place, on va définir un ensemble de fonctions décrivant un comportement : par exemple, la classe de types Eq
en Haskell définit le comportement « peut être comparé » et regroupe les fonctions ==
et /=
(en C++, on aurait !=
) ; la classe de types Num
définit le comportement « se comporte comme un nombre » et définit l’addition, la multiplication, l’inverse, la valeur absolue et 2-3 autres fonctions similaires.
On va ensuite définir un type quelconque, et dire que ce type implémente la classe de types voulue, ce qui va nous permettre de définir le fonctionnement de ces fonctions pour ce type-là, alors même que des fonctions du même nom existent déjà.
En Rust, c’est pareil, sauf que cette implémentation de fonctions « génériques » se fait avec une syntaxe similaire à celle des méthodes (impl
et utilisation par objet.fonction()
), ce dont je n’ai jamais compris l’utilité.
Il y a également autre chose. Je suppose que tu as eu l’occasion de voir les fonctions paramétrées, équivalent à peu près aux templates du C++ ? Eh bien les traits/classes de types te permettent de poser ce que l’on appelle des contraintes de types sur les paramètres de ces fonctions : tu vas spécifier que tous les types ne sont pas acceptés en paramètre, mais uniquement ceux qui implémentent un certain trait.
Par exemple, pour reprendre l’exemple de informaticienzero, tu pourras écrire une fonction dis_moi_bonjour()
qui n’accepte que les paramètres qui implémentent le trait Animal
, et dont on est alors certain qu’ils possèdent la fonction presentation()
.
Il n’y a à l’heure actuelle pas d’équivalent exact de cela en C++, mais c’est prévu pour le prochain standard.
TL;DR : ça sert à faire de la surcharge de fonctions et c’est le seul moyen d’en faire en Rust. Ça aide aussi à faire de meilleures fonctions paramétrées.