Lekcje modułu (2/2)
Cechy i ograniczenia (Traits / Trait Bounds)
Traity definiują zachowanie, które posiada konkretny typ i które może być współdzielone z innymi typami. Możemy używać traitów do zdefiniowania zestawu metod reprezentujących określoną wspólną funkcjonalność lub interfejs, podobnie jak interfejsy w innych językach programowania.
Trait bounds (ograniczenia traitu) pozwalają określić, że typ ogólny (generyczny) musi implementować dany trait, gwarantując, że wymagane metody będą dostępne w czasie kompilacji.
Definiowanie i implementowanie traitu
Aby zdefiniować trait, używamy słowa kluczowego trait wraz z sygnaturami metod, które typy muszą zaimplementować:
pub trait Summary {
fn summarize(&self) -> String;
}
Aby zaimplementować trait dla konkretnego typu, używamy składni impl TraitName for TypeName:
pub struct NewsArticle {
pub headline: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}", self.headline)
}
}
Trait Bounds (Ograniczenia Traitu)
Kiedy piszemy funkcje generyczne, możemy ograniczyć parametry typu, aby upewnić się, że implementują one określony trait. Standardowa składnia to <T: Trait>:
pub fn notify<T: Summary>(item: &T) {
println!("Notifica: {}", item.summarize());
}
Alternatywnie, dla bardziej skomplikowanych sygnatur, możemy użyć klauzuli where:
pub fn notify_advanced<T>(item: &T)
where
T: Summary
{
println!("Notifica: {}", item.summarize());
}
Spróbuj sam
Ćwiczenie 1: Trait Summary
Zdefiniuj trait o nazwie Summary zawierający sygnaturę metody fn summarize(&self) -> String;. Następnie zdefiniuj strukturę (struct) NewsArticle z polem headline typu String i zaimplementuj dla niej trait Summary tak, aby metoda summarize zwracała wartość pola headline.
Pokaż wskazówkę
Zdefiniuj trait `Summary`i strukturę`NewsArticle`. Zaimplementuj za pomocą `impl Summary for NewsArticle`klonując pole`self.headline.clone()`.
Rozwiązanie dostępne po 3 próbach
Ćwiczenie 2: Trait Bounds z print_summary
Opierając się na kodzie z poprzedniego ćwiczenia, zdefiniuj funkcję generyczną o nazwie print_summary<T>, która przyjmuje parametr item typu &T. Zastosuj ograniczenie (trait bound) tak, aby T musiało implementować trait Summary. Wewnątrz funkcji wypisz na ekranie wynik zwrócony przez item.summarize().
Pokaż wskazówkę
Użyj sygnatury `fn print_summary<T: Summary>(item: &T)`i wywołaj`item.summarize()`wewnątrz`println!`.
Rozwiązanie dostępne po 3 próbach
Ćwiczenie 3: Obliczanie pola powierzchni za pomocą Traitu
Zdefiniuj trait o nazwie Area z metodą fn area(&self) -> f64;. Utwórz strukturę Circle zawierającą pole radius typu f64 i zaimplementuj dla niej trait Area, obliczając pole powierzchni (wzór: radius * radius * 3.14159).
Pokaż wskazówkę
Zdefiniuj trait `Area`i strukturę`Circle`. Zaimplementuj `area(&self)` przy użyciu wzoru na pole koła.
Rozwiązanie dostępne po 3 próbach