ProgrammationDéveloppeur backend Rust

Comment les énumérations avec des données associées sont-elles implémentées en Rust et comment utiliser le pattern matching pour les traiter dans des applications réelles ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

En Rust, les énumérations (enums) peuvent stocker non seulement des valeurs (variants), mais aussi des données associées (payload). Cela les rend particulièrement utiles pour créer des types algébriques de données, par exemple, pour représenter des états ou des messages avec des paramètres. Par exemple :

enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), }

Pour traiter de tels enums, on utilise généralement l'opérateur match, qui permet de décomposer les valeurs imbriquées de chaque variante :

let msg = Message::Move { x: 10, y: 20 }; match msg { Message::Quit => println!("Message de sortie"), Message::Move { x, y } => println!("Déplacer vers ({}, {})", x, y), Message::Write(text) => println!("Texte : {}", text), Message::ChangeColor(r, g, b) => println!("Changer la couleur en ({}, {}, {})", r, g, b), }

Cette approche permet de traiter de manière sûre et explicite tous les cas possibles, ce qui minimise les erreurs dans la logique du programme.

Question piège

Pourquoi n'existe-t-il pas de null pour les enums en Rust, et que renverra une tentative de matching avec une variante inexistante ?

Une réponse incorrecte fréquente : "Le compilateur ignorera l'erreur si tous les cas enum ne sont pas traités dans le match."

En réalité, le compilateur renverra une erreur si toutes les variantes possibles ne sont pas prises en compte, ou exigera d'ajouter un catch-all (_). Par exemple :

enum Status { Ok, Err(String) } let st = Status::Ok; match st { Status::Ok => println!("Ok"), // Si on oublie Status::Err, le compilateur se plaindra }

Exemples d'erreurs réelles dues à une mauvaise compréhension du sujet


Histoire Dans un projet, lors de l'expansion d'un enum, on n'a pas ajouté le traitement d'une nouvelle variante dans le match dans tous les endroits où il était utilisé. Cela a conduit à un panic ! lors de la sortie, car le match n'était pas exhaustif, les tests ne couvrant pas tous les cas.


Histoire Dans un autre cas, on a essayé de comparer un enum avec == sans implémenter PartialEq pour des variantes complexes avec des données associées, ce qui a provoqué une erreur de compilation inattendue.


Histoire L'équipe a utilisé un catch-all (_) pour traiter les variants, et plus tard, lors de l'ajout de nouvelles variantes, cela a conduit à ce que la logique ignore silencieusement de nouveaux cas, ce qui a causé des défauts difficiles à trouver.