Le trait Display
Fait partie de la section Object Oriented Programming du Journey Rust de Coddy — leçon 36 sur 61.
Alors que Debug est idéal pour les développeurs inspectant des données, le trait Display est conçu pour une sortie destinée à l'utilisateur. C'est ce qui alimente le formateur {} dans println!. Contrairement à Debug, Rust ne peut pas dériver automatiquement Display—vous devez l'implémenter manuellement.
Pour implémenter Display, vous devez importer le module fmt et implémenter la méthode fmt :
use std::fmt;
struct Temperature {
celsius: f64,
}
impl fmt::Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}°C", self.celsius)
}
}
La méthode fmt reçoit un Formatter et retourne un fmt::Result. Vous utilisez la macro write! pour formater votre sortie, en accédant aux champs de la structure via self.
Maintenant, vous pouvez afficher la structure avec le formateur standard {} :
let temp = Temperature { celsius: 23.5 };
println!("{}", temp); // 23.5°C
La différence clé : l'affichage Debug montre la structure de vos données (utile pour le débogage), tandis que l'affichage Display est soigné et destiné aux utilisateurs finaux. Une struct peut implémenter les deux — utilisez {:?} pour le débogage et {} pour un affichage propre.
Défi
FacileCréons un système d'affichage de produits convivial ! Alors que Debug montre la structure brute de vos données, le trait Display vous permet de concevoir une sortie soignée et lisible par l'homme, parfaite pour les utilisateurs finaux.
Vous organiserez votre code sur deux fichiers :
product.rs: Définissez une structureProductpublique avec deux champs publics :name(String) etprice(f64). Implémentez le traitDisplaypour votre structure afin qu'elle se formate comme{name} - ${price}. N'oubliez pas d'importerstd::fmtet d'utiliser la macrowrite!à l'intérieur de votre méthodefmt.main.rs: Importez votre module product et créez une instance deProducten utilisant les entrées fournies. Affichez le produit en utilisant le formateur standard{}pour montrer votre sortie d'affichage personnalisée.
Le trait Display nécessite que vous implémentiez la méthode fmt manuellement — Rust ne peut pas la dériver automatiquement comme Debug. Cela vous donne un contrôle total sur la façon dont votre type apparaît aux utilisateurs.
Votre sortie doit afficher le produit dans un format propre et convivial :
{name} - ${price}Par exemple, avec les entrées Wireless Mouse et 29.99 :
Wireless Mouse - $29.99Vous recevrez deux entrées : le nom du produit et le prix (à analyser comme f64).
Aide-mémoire
Le trait Display est conçu pour une sortie destinée à l'utilisateur et alimente le formateur {} dans println!. Contrairement à Debug, il doit être implémenté manuellement.
Pour implémenter Display, importez le module fmt et implémentez la méthode fmt :
use std::fmt;
struct Temperature {
celsius: f64,
}
impl fmt::Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}°C", self.celsius)
}
}
La méthode fmt reçoit un Formatter et renvoie un fmt::Result. Utilisez la macro write! pour formater la sortie, en accédant aux champs de la structure via self.
Affichez la structure avec le formateur {} :
let temp = Temperature { celsius: 23.5 };
println!("{}", temp); // 23.5°C
Différence clé : Debug ({:?}) affiche la structure des données pour le débogage, tandis que Display ({}) fournit une sortie soignée pour les utilisateurs finaux.
Essayez vous-même
mod product;
use product::Product;
fn main() {
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
let mut price_input = String::new();
std::io::stdin().read_line(&mut price_input).expect("Failed to read line");
let price: f64 = price_input.trim().parse().expect("Failed to parse price");
// TODO: Créer une instance de Product avec le name et le price
// TODO: Afficher le produit en utilisant le formateur {}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
1Méthodes et comportement
Introduction aux blocs d'implémentationLe paramètre SelfMéthodes mutablesFonctions associéesBlocs d'implémentation multiplesChaînage de méthodesRécapitulatif - Actions sur le rectangle4Projet : Animal virtuel
Définir l'animalNourrir l'animal7Traits standards
Le trait DebugLe trait DisplayClone et CopyLes traits d'égalitéRécapitulatif - Point affichable10Projet : Système de documents
Le trait DrawComposant texte2Encapsulation et modules
Bases des modulesLe mot-clé publicChamps privésGettersSettersRécapitulatif - Casier sécurisé5Généricité
Structures génériquesMéthodes génériquesPlusieurs types génériquesFonctions génériquesRécapitulatif - Point de coordonnées8Les Traits comme contraintes
Syntaxe des contraintes de traitContraintes multiplesLa clause whereRetourner des types avec des traitsRécapitulatif - Afficheur générique11Design Patterns en Rust
Le pattern NewtypeCompositionLe trait DropFrom et IntoRécapitulatif - Mock de Smart Pointer3Enums avancées
Enums avec donnéesMéthodes sur les EnumsMatching des variantes de donnéesL'Enum Option revisitéeRécapitulatif - Enum Shape6Définition des Traits
Qu'est-ce qu'un Trait ?Implémenter des TraitsImplémentations par défautRedéfinir les comportements par défautTraits avec paramètresRécapitulatif - Lecteur multimédia