Menu
Coddy logo textTech

Redéfinir les comportements par défaut

Fait partie de la section Object Oriented Programming du Journey Rust de Coddy — leçon 32 sur 61.

Les implémentations par défaut sont pratiques, mais parfois un type a besoin d'un comportement qui diffère de la norme. Lorsque cela se produit, vous pouvez surcharger le comportement 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)
    }
}

Même si Greet fournit une méthode greet par défaut, Robot la remplace entièrement par sa propre version. Lorsque vous appelez greet() sur un Robot, Rust utilise l'implémentation 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 contentent du comportement par défaut n'ont rien à écrire, tandis que les types nécessitant un comportement spécialisé peuvent redéfinir uniquement les méthodes qui les intéressent. Le trait garantit toujours que chaque type implémentant dispose de la méthode.

challenge icon

Défi

Facile

Construisons un système de notification où différents types d'alertes peuvent personnaliser leurs messages ! Vous allez créer un trait avec une implémentation par défaut, puis faire en sorte qu'un type utilise cette valeur par défaut tandis qu'un autre la surcharge avec un comportement personnalisé.

Vous organiserez votre code sur trois fichiers :

  • notifiable.rs : Définissez un trait public Notifiable avec une méthode notify(&self) -> String qui possède une implémentation par défaut retournant "Alert: Something happened!".
  • alerts.rs : Créez deux structures publiques qui implémentent votre trait différemment :
    • GenericAlert — une structure unité (unit struct) qui utilise la notification par défaut (bloc impl vide).
    • UrgentAlert — une structure avec un champ public message (String) qui surcharge le comportement par défaut pour retourner "URGENT: {message}"{message} est son message stocké.
  • main.rs : Rassemblez vos modules et démontrez les deux comportements. Créez un GenericAlert et un UrgentAlert en utilisant l'entrée fournie, puis affichez leurs notifications.

L'idée clé ici est que GenericAlert bénéficie gratuitement du comportement par défaut, tandis que UrgentAlert fournit sa propre version spécialisée en définissant la méthode dans son bloc impl.

Votre sortie doit suivre ce format :

Alert: Something happened!
URGENT: {message}

Par exemple, avec l'entrée Server is down! :

Alert: Something happened!
URGENT: Server is down!

Vous recevrez une entrée : le message pour l'alerte urgente.

Aide-mémoire

Vous pouvez surcharger les implémentations de trait par défaut en fournissant votre propre implémentation dans le bloc impl :

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)
    }
}

let bot = Robot { id: 42 };
println!("{}", bot.greet());  // BEEP BOOP. Unité 42 en ligne.

Les types qui n'ont pas besoin d'un comportement personnalisé peuvent utiliser un bloc impl vide pour accepter l'implémentation par défaut, tandis que les types nécessitant un comportement spécialisé peuvent surcharger des méthodes spécifiques en les définissant avec la même signature.

Essayez vous-même

mod notifiable;
mod alerts;

use alerts::{GenericAlert, UrgentAlert};
use notifiable::Notifiable;

fn main() {
    // Lire l'entrée pour le message d'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 de UrgentAlert avec le message d'entrée

    // TODO: Imprimer la notification de GenericAlert

    // TODO: Imprimer la notification de UrgentAlert
}
quiz iconTestez-vous

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