Menu
Coddy logo textTech

Implementacje domyślne

Część sekcji Programowanie obiektowe ścieżki Rust w Coddy. Lekcja 31 z 61.

Jak dotąd każda zdefiniowana przez nas metoda cechy była tylko sygnaturą: wymaganiem bez treści. Ale co, jeśli większość typów implementujących cechę używałaby tej samej logiki? Rust pozwala podać implementację domyślną bezpośrednio w definicji cechy.

Zamiast kończyć sygnaturę metody średnikiem, dodajesz ciało:

trait Greet {
    fn greet(&self) -> String {
        String::from("Hello there!")
    }
}

Teraz każdy typ implementujący Greet automatycznie otrzymuje tę metodę, bez konieczności pisania kodu w bloku impl:

struct Guest;

impl Greet for Guest {}

let visitor = Guest;
println!("{}", visitor.greet());  // Cześć!

Puste impl Greet for Guest {} jest poprawne, ponieważ trait już udostępnia to zachowanie. Struktura po prostu „deklaruje zgodność” z traitem i otrzymuje domyślną metodę za darmo.

Ten wzorzec jest przydatny, gdy chcesz zdefiniować współdzielone zachowanie, które sprawdza się w większości przypadków. Typy, które potrzebują czegoś innego, mogą nadpisać zachowanie domyślne (czego nauczysz się w następnej lekcji), a typy, którym odpowiada standardowe zachowanie, nie muszą go powtarzać.

challenge icon

Wyzwanie

Łatwy

Poznajmy możliwości domyślnych implementacji, budując system powiadomień! Utworzysz trait, który od razu zapewnia standardowe zachowanie, dzięki czemu typy mogą z niego skorzystać bez pisania powtarzalnego kodu.

Podzielisz swój kod na trzy pliki:

  • notifiable.rs: Zdefiniuj publiczny trait Notifiable z metodą notify(&self) -> String, która ma domyślną implementację. Powinna ona zwracać "You have a new notification!". Każdy typ implementujący ten trait automatycznie otrzyma to zachowanie, bez konieczności wpisywania czegokolwiek w bloku impl.
  • alerts.rs: Utwórz dwie proste publiczne struktury jednostkowe, które implementują Twój trait:
    • EmailAlert: implementuje Notifiable z pustym blokiem impl (korzysta z domyślnej implementacji)
    • SystemAlert: również implementuje Notifiable z pustym blokiem impl (korzysta z domyślnej implementacji)
    Obie struktury automatycznie otrzymają domyślną wiadomość powiadomienia — nie musisz pisać żadnych treści metod!
  • main.rs: Połącz moduły i pokaż, że oba typy alertów korzystają z tego samego domyślnego zachowania. Utwórz instancje obu struktur i wywołaj ich metody notify.

W pliku głównym utwórz EmailAlert i SystemAlert, a następnie wypisz ich powiadomienia w osobnych wierszach.

Oczekiwany wynik:

You have a new notification!
You have a new notification!

Zauważ, że oba typy generują identyczny wynik: na tym polega zaleta domyślnych implementacji! Żadna ze struktur nie musiała zawierać kodu metody notify, a mimo to obie mają w pełni funkcjonalne zachowanie związane z powiadomieniami. W następnej lekcji dowiesz się, jak nadpisywać te wartości domyślne, gdy typ wymaga własnego zachowania.

Spróbuj swoich sił

mod notifiable;
mod alerts;

use notifiable::Notifiable;
use alerts::{EmailAlert, SystemAlert};

fn main() {
    // TODO: Utwórz instancję EmailAlert
    
    // TODO: Utwórz instancję SystemAlert
    
    // TODO: Wyświetl powiadomienie z EmailAlert
    
    // TODO: Wyświetl powiadomienie z SystemAlert
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Rust online