Redéfinir les comportements par défaut
Fait partie de la section Programmation Orientée Objet du Journey Rust de Coddy. Leçon 32 sur 61.
Les implémentations par défaut sont pratiques, mais parfois un type doit avoir un comportement différent de celui standard. Dans ce cas, vous pouvez remplacer l’implémentation par défaut en fournissant votre propre implémentation dans le bloc impl.
Définissez simplement la méthode avec la même signature, mais incluez votre logique personnalisée :
trait Greet {
fn greet(&self) -> String {
String::from("Hello there!")
}
}
struct Robot {
id: u32,
}
impl Greet for Robot {
fn greet(&self) -> String {
format!("BEEP BOOP. Unit {} online.", self.id)
}
}
Bien que Greet fournisse une méthode greet default, Robot la remplace entièrement par sa propre version. Lorsque vous appelez greet() sur un Robot, Rust utilise l’implementation personnalisée :
let bot = Robot { id: 42 };
println!("{}", bot.greet()); // BEEP BOOP. Unité 42 en ligne.
Cela vous offre de la flexibilité : les types qui se satisfont du comportement par défaut n’ont rien à écrire, tandis que les types qui nécessitent un comportement spécialisé peuvent remplacer uniquement les méthodes qui les intéressent. Le trait garantit toujours que chaque type qui l’implémente dispose de la méthode.
Défi
FacileConstruisons un système de notification dans lequel différents types d’alertes peuvent personnaliser leurs messages ! Tu vas créer un trait avec une implémentation par défaut, puis faire en sorte qu’un type utilise la valeur par défaut tandis qu’un autre la remplace par un comportement personnalisé.
Tu organiseras ton code dans trois fichiers :
notifiable.rs: définis un trait publicNotifiableavec une méthodenotify(&self) -> Stringqui possède une implémentation par défaut renvoyant"Alert: Something happened!".alerts.rs: crée deux structures publiques qui implémentent ton trait de manière différente :GenericAlert: une structure unitaire qui utilise la notification par défaut (bloc impl vide)UrgentAlert: une structure avec un champ publicmessage(String) qui remplace la valeur par défaut pour renvoyer"URGENT: {message}", où{message}est son message enregistré
main.rs: regroupe tes modules et démontre les deux comportements. Crée unGenericAlertet unUrgentAlertà l’aide de l’entrée fournie, puis affiche leurs notifications.
L’idée essentielle est que GenericAlert obtient gratuitement un comportement grâce à la valeur par défaut, tandis que UrgentAlert fournit sa propre version spécialisée en définissant la méthode dans son bloc impl.
Ta sortie doit respecter ce format :
Alert: Something happened!
URGENT: {message}Par exemple, avec l’entrée Server is down! :
Alert: Something happened!
URGENT: Server is down!Tu recevras une entrée : le message de l’alerte urgente.
Essayez vous-même
mod notifiable;
mod alerts;
use alerts::{GenericAlert, UrgentAlert};
use notifiable::Notifiable;
fn main() {
// Lire l'entrée pour le message de l'alerte urgente
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let message = input.trim().to_string();
// TODO: Créer une instance de GenericAlert
// TODO: Créer une instance d'UrgentAlert avec le message d'entrée
// TODO: Afficher la notification de GenericAlert
// TODO: Afficher la notification d'UrgentAlert
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
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édiaEntraînez-vous par vous-même : Compilateur Rust en ligne