Menu
Coddy logo textTech

Standardimplementierungen überschreiben

Teil des Abschnitts Object Oriented Programming der Rust-Journey von Coddy — Lektion 32 von 61.

Standardimplementierungen sind praktisch, aber manchmal benötigt ein Typ ein Verhalten, das vom Standard abweicht. Wenn dies der Fall ist, können Sie den Standard überschreiben, indem Sie Ihre eigene Implementierung im impl-Block bereitstellen.

Definieren Sie die Methode einfach mit derselben Signatur, aber fügen Sie Ihre eigene Logik hinzu:

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

Obwohl Greet eine standardmäßige greet-Methode bereitstellt, ersetzt Robot diese vollständig durch seine eigene Version. Wenn Sie greet() auf einem Robot aufrufen, verwendet Rust die benutzerdefinierte Implementierung:

let bot = Robot { id: 42 };
println!("{}", bot.greet());  // BEEP BOOP. Einheit 42 online.

Dies bietet Ihnen Flexibilität – Typen, die mit dem Standard zufrieden sind, müssen nichts schreiben, während Typen, die ein spezialisiertes Verhalten benötigen, nur die Methoden überschreiben können, die für sie relevant sind. Das Trait garantiert weiterhin, dass jeder implementierende Typ über die Methode verfügt.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Benachrichtigungssystem bauen, bei dem verschiedene Alarmtypen ihre Nachrichten anpassen können! Sie werden ein Trait mit einer Standardimplementierung erstellen und dann einen Typ dazu bringen, den Standard zu verwenden, während ein anderer ihn mit benutzerdefiniertem Verhalten überschreibt.

Sie werden Ihren Code über drei Dateien organisieren:

  • notifiable.rs: Definieren Sie ein öffentliches Notifiable-Trait mit einer Methode notify(&self) -> String, die eine Standardimplementierung hat, welche "Alert: Something happened!" zurückgibt.
  • alerts.rs: Erstellen Sie zwei öffentliche Structs, die Ihr Trait unterschiedlich implementieren:
    • GenericAlert — ein Unit-Struct, das die Standardbenachrichtigung verwendet (leerer impl-Block)
    • UrgentAlert — ein Struct mit einem öffentlichen message-Feld (String), das den Standard überschreibt, um "URGENT: {message}" zurückzugeben, wobei {message} die gespeicherte Nachricht ist
  • main.rs: Führen Sie Ihre Module zusammen und demonstrieren Sie beide Verhaltensweisen. Erstellen Sie ein GenericAlert und ein UrgentAlert unter Verwendung der bereitgestellten Eingabe und geben Sie dann deren Benachrichtigungen aus.

Die entscheidende Erkenntnis hierbei ist, dass GenericAlert kostenloses Verhalten durch den Standard erhält, während UrgentAlert seine eigene spezialisierte Version bereitstellt, indem es die Methode in seinem impl-Block definiert.

Ihre Ausgabe sollte diesem Format folgen:

Alert: Something happened!
URGENT: {message}

Zum Beispiel mit der Eingabe Server is down!:

Alert: Something happened!
URGENT: Server is down!

Sie erhalten eine Eingabe: die Nachricht für den dringenden Alarm (Urgent Alert).

Spickzettel

Sie können Standard-Trait-Implementierungen überschreiben, indem Sie Ihre eigene Implementierung im impl-Block bereitstellen:

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 online.

Typen, die kein benutzerdefiniertes Verhalten benötigen, können einen leeren impl-Block verwenden, um die Standardimplementierung zu akzeptieren, während Typen, die ein spezialisiertes Verhalten erfordern, bestimmte Methoden überschreiben können, indem sie diese mit derselben Signatur definieren.

Probier es selbst

mod notifiable;
mod alerts;

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

fn main() {
    // Eingabe für die dringende Alarmmeldung lesen
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let message = input.trim().to_string();

    // TODO: Erstelle eine GenericAlert-Instanz

    // TODO: Erstelle eine UrgentAlert-Instanz mit der eingegebenen Nachricht

    // TODO: Gib die Benachrichtigung von GenericAlert aus

    // TODO: Gib die Benachrichtigung von UrgentAlert aus
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Object Oriented Programming