Menu
Coddy logo textTech

Wiele ograniczeń

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

Czasami pojedyncze ograniczenie cechy nie wystarcza. Możesz potrzebować typu generycznego, który można zarówno wypisać i który udostępnia podsumowanie. Rust pozwala wymagać wielu cech za pomocą składni +.

Oto jak określić, że typ musi implementować dwa traitsy:

use std::fmt::Display;

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

fn announce<T: Display + Summary>(item: T) {
    println!("Breaking news: {}", item);
    println!("Summary: {}", item.summarize());
}

Ograniczenie T: Display + Summary oznacza „T musi implementować zarówno Display, jak i Summary”. Wewnątrz funkcji możesz korzystać z możliwości obu cech: drukować za pomocą {} (z Display) i wywoływać summarize() (z Summary).

Możesz łączyć tyle cech, ile potrzebujesz:

fn process<T: Display + Summary + Clone>(item: T) {
    // Może wyświetlać, podsumowywać ORAZ klonować
}

Ten wzorzec jest niezbędny, gdy Twoja funkcja opiera się na wielu zachowaniach. Zamiast akceptować dowolny typ i mieć nadzieję, że zadziała, jawnie deklarujesz dokładnie, jakie możliwości są wymagane, a kompilator sprawdza to podczas kompilacji.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system inspekcji produktów, który wymaga od elementów wielu możliwości! Utworzysz funkcję generyczną, która akceptuje wyłącznie typy implementujące zarówno niestandardowy trait, jak i standardowy trait, pokazując, jak składnia + łączy wiele ograniczeń.

Podzielisz swój kod na dwa pliki:

  • product.rs: Zdefiniuj publiczny trait Inspectable z metodą o nazwie inspect, która przyjmuje &self i zwraca String zawierający szczegóły inspekcji. Następnie utwórz publiczną strukturę Gadget z publicznymi polami name (String) i serial (u32). Twoja struktura Gadget powinna implementować zarówno Inspectable (zwracając Inspecting: {name}), jak i std::fmt::Display (formatując wynik jako {name} (SN: {serial})). Na koniec utwórz publiczną funkcję generyczną o nazwie full_report, która przyjmuje dowolny typ T implementujący zarówno Display, jak i Inspectable. Funkcja powinna wypisać dwa wiersze: najpierw element przy użyciu formatera {}, a następnie wynik wywołania inspect().
  • main.rs: Dołącz moduł produktu i utwórz instancję Gadget na podstawie podanych danych wejściowych. Wywołaj full_report ze swoim gadżetem, aby pokazać, że spełnia on wymagania obu traitów.

Zaletą wielu ograniczeń jest to, że funkcja full_report może korzystać z możliwości obu traitów, ładnie wyświetlając element ORAZ pobierając szczegóły inspekcji — wszystko to jest gwarantowane podczas kompilacji.

Wynik powinien pokazywać zarówno format wyświetlania, jak i rezultat inspekcji:

{name} (SN: {serial})
Inspecting: {name}

Na przykład dla danych wejściowych Smartwatch i 98765:

Smartwatch (SN: 98765)
Inspecting: Smartwatch

Otrzymasz dwa dane wejściowe: nazwę gadżetu i numer seryjny (parsuj jako u32).

Spróbuj swoich sił

mod product;

use product::{Gadget, full_report};

fn main() {
    // Wczytaj dane wejściowe
    let mut name = String::new();
    std::io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim().to_string();
    
    let mut serial_input = String::new();
    std::io::stdin().read_line(&mut serial_input).expect("Failed to read line");
    let serial: u32 = serial_input.trim().parse().expect("Failed to parse serial");
    
    // TODO: Utwórz instancję Gadget z nazwą i numerem seryjnym
    
    // TODO: Wywołaj full_report, przekazując swój gadżet
}
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