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.
Wyzwanie
ŁatwyStwó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ęNotifyz metodą o nazwiemessage, która przyjmuje&selfi zwracaString. Następnie utwórz dwie publiczne struktury implementujące tę cechę:Email: z publicznym polemsubject(String). Metodamessagepowinna zwracaćEmail: {subject}SMS: z publicznym polemcontent(String). Metodamessagepowinna zwracaćSMS: {content}
send_notification, która przyjmuje dowolny typTimplementujący cechęNotify. Ta funkcja powinna wypisać wynik wywołaniamessage()na elemencie.main.rs: Zaimportuj moduł powiadomień i użyj podanych danych wejściowych, aby utworzyć instancjeEmailiSMS. Wywołajsend_notificationdla każdej z nich, aby pokazać, że twoja funkcja generyczna działa z dowolnym typem implementującymNotify.
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
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Metody i zachowanie
Wprowadzenie do bloków implementacjiParametr selfMetody modyfikująceFunkcje powiązaneWiele bloków implementacjiŁańcuchowe wywoływanie metodPowtórzenie — działania na prostokącie4Projekt: Wirtualne zwierzątko
Definiowanie zwierzątkaKarmienie zwierzątka7Standardowe cechy
Cecha DebugCecha DisplayClone i CopyCechy równościPowtórka – punkt do wydrukowania10Projekt: System dokumentów
Trait DrawKomponent tekstowy2Hermetyzacja i moduły
Podstawy modułówSłowo kluczowe publicPola prywatneGetterySetteryPodsumowanie — bezpieczna skrytka5Typy generyczne
Struktury generyczneMetody generyczneWiele typów generycznychFunkcje generycznePodsumowanie – punkt współrzędnych8Cechy jako ograniczenia
Składnia ograniczeń cechWiele ograniczeńKlauzula whereZwracanie typów z użyciem cechPodsumowanie — generyczna drukarka11Wzorce projektowe w Rust
Wzorzec NewtypeKompozycjaTrait DropFrom i IntoPodsumowanie — atrapowy inteligentny wskaźnik3Zaawansowane typy wyliczeniowe
Typy wyliczeniowe z danymiMetody typów wyliczeniowychDopasowywanie wariantów danychTyp wyliczeniowy Option — powtórzeniePodsumowanie — typ wyliczeniowy Shape6Definiowanie cech
Czym jest cecha?Implementowanie cechImplementacje domyślneNadpisywanie wartości domyślnychCechy z parametramiPowtórzenie — odtwarzacz multimedialnyPoćwicz samodzielnie: Kompilator Rust online