Menu
Coddy logo textTech

Składnia ograniczeń cech

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

Do tej pory nauczyłeś się definiować cechy i implementować je dla struktur. Pracowałeś także z typami generycznymi, aby pisać elastyczny kod. Teraz czas połączyć te koncepcje: użyć cech, aby ograniczyć typy, które może przyjmować funkcja generyczna.

Rozważ funkcję generyczną, która musi wywołać określoną metodę na swoim parametrze. Bez żadnych ograniczeń Rust nie gwarantuje, że typ T ma tę metodę:

fn print_info<T>(item: T) {
    println!("{}", item.summarize());  // Błąd! T może nie mieć metody summarize()
}

Rozwiązaniem są ograniczenia cech. Dodając : TraitName po parametrze generycznym, informujesz Rust, że T musi implementować tę cechę:

trait Summary {
    fn summarize(&self) -> String;
}

fn print_info<T: Summary>(item: T) {
    println!("{}", item.summarize());  // Teraz Rust wie, że ta metoda istnieje
}

Składnia <T: Summary> oznacza: „T to dowolny typ, który implementuje Summary”. Teraz funkcja akceptuje tylko typy, które mają wymagane zachowanie. Jeśli spróbujesz przekazać typ, który nie implementuje Summary, kompilator odrzuci go i wyświetli jasny komunikat o błędzie.

Ten wzorzec jest potężny, ponieważ pozwala pisać kod ogólny, który nadal ma dostęp do określonych funkcjonalności. Twoja funkcja pozostaje elastyczna i działa z dowolnym typem, ale tylko z tymi typami, które zapewniają potrzebne zachowanie.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system powiadomień, który używa ograniczeń cech, aby mieć pewność, że można wysyłać tylko prawidłowo sformatowane wiadomości! Utworzysz funkcję generyczną, która przyjmuje dowolny typ implementujący określoną cechę, demonstrując, w jaki sposób ograniczenia cech ograniczają parametry generyczne.

Rozmieścisz kod w dwóch plikach:

  • notification.rs: Zdefiniuj publiczną cechę Notify z metodą o nazwie message, która przyjmuje &self i zwraca String. Następnie utwórz dwie publiczne struktury implementujące tę cechę:
    • Email: z publicznym polem subject (String). Metoda message powinna zwracać Email: {subject}
    • SMS: z publicznym polem content (String). Metoda message powinna zwracać SMS: {content}
    Na koniec utwórz publiczną funkcję generyczną o nazwie send_notification, która przyjmuje dowolny typ T implementujący cechę Notify. Ta funkcja powinna wypisać wynik wywołania message() na elemencie.
  • main.rs: Zaimportuj moduł powiadomień i użyj podanych danych wejściowych, aby utworzyć instancje Email i SMS. Wywołaj send_notification dla każdej z nich, aby pokazać, że twoja funkcja generyczna działa z dowolnym typem implementującym Notify.

Najważniejsze jest to, że send_notification nie zna konkretnego typu, który otrzymuje. Wie jedynie, że typ ten potrafi utworzyć wiadomość. Ograniczenie cechy T: Notify gwarantuje tę możliwość.

Wynik powinien pokazywać wysłanie obu powiadomień:

Email: {subject}
SMS: {content}

Na przykład dla danych wejściowych Meeting Tomorrow i On my way!:

Email: Meeting Tomorrow
SMS: On my way!

Otrzymasz dwa dane wejściowe: temat wiadomości e-mail i treść SMS-a.

Spróbuj swoich sił

mod notification;

use notification::{Email, SMS, send_notification};

fn main() {
    // Odczytaj dane wejściowe
    let mut subject = String::new();
    std::io::stdin().read_line(&mut subject).expect("Failed to read line");
    let subject = subject.trim().to_string();
    
    let mut content = String::new();
    std::io::stdin().read_line(&mut content).expect("Failed to read line");
    let content = content.trim().to_string();
    
    // TODO: Utwórz instancję Email z tematem
    
    // TODO: Utwórz instancję SMS z treścią
    
    // TODO: Wywołaj send_notification z email
    
    // TODO: Wywołaj send_notification z sms
}
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