Menu
Coddy logo textTech

Klauzula where

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

W miarę dodawania kolejnych ograniczeń cech sygnatury funkcji mogą stawać się trudne do odczytania. Rozważ funkcję z wieloma parametrami generycznymi, z których każdy wymaga kilku cech:

fn complex_operation<T: Display + Clone, U: Debug + Summary>(first: T, second: U) {
    // ...
}

To działa, ale sygnatura staje się coraz bardziej złożona. Klauzula where oferuje czytelniejszą alternatywę, przenosząc ograniczenia cech za listę parametrów:

fn complex_operation<T, U>(first: T, second: U)
where
    T: Display + Clone,
    U: Debug + Summary,
{
    // ...
}

Obie wersje są funkcjonalnie identyczne: klauzula where służy wyłącznie czytelności. Wymagania dotyczące każdego typu znajdują się w osobnym wierszu, dzięki czemu łatwo sprawdzić, czego potrzebuje każdy parametr generyczny.

Klauzula where staje się szczególnie przydatna, gdy ograniczenia są złożone lub gdy masz wiele parametrów generycznych. Dzięki niej nazwa funkcji i parametry są od razu widoczne, a ograniczenia są wymienione osobno poniżej. To preferowany styl w większości baz kodu Rust, gdy ograniczenia wykraczają poza proste T: Trait.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system przetwarzania danych, który używa klauzuli where, aby zachować czytelność złożonych ograniczeń cech! Utworzysz funkcję generyczną z wieloma parametrami typów, z których każdy wymaga innych cech, i uporządkujesz ograniczenia za pomocą składni where.

Rozmieścisz kod w dwóch plikach:

  • processor.rs: Zdefiniuj dwie publiczne cechy i funkcję generyczną, która używa ich obu:
    • Summarize: cecha z metodą summary, która przyjmuje &self i zwraca String
    • Validate: cecha z metodą validate, która przyjmuje &self i zwraca bool
    Następnie utwórz publiczną funkcję generyczną o nazwie process_items, która przyjmuje dwa parametry różnych typów generycznych. Użyj klauzuli where, aby określić, że pierwszy typ musi implementować zarówno Clone, jak i Summarize, a drugi typ musi implementować Validate. Funkcja powinna wypisać podsumowanie pierwszego elementu, a następnie informację, czy drugi element jest prawidłowy.
  • main.rs: Utwórz dwie publiczne struktury implementujące wymagane cechy:
    • Article: z publicznym polem title (String). Zaimplementuj Summarize, aby zwracała Article: {title}, i wyprowadź cechę Clone.
    • Form: z publicznym polem filled (bool). Zaimplementuj Validate, aby zwracała wartość filled.
    Użyj podanych danych wejściowych, aby utworzyć Article i Form, a następnie wywołaj process_items, przekazując oba elementy.

Klauzula where sprawia, że sygnatura funkcji jest znacznie czytelniejsza niż upychanie wszystkich ograniczeń w nawiasach ostrych. Wymagania każdego typu są zapisane w osobnym wierszu, dzięki czemu łatwo zobaczyć, czego potrzebuje każdy parametr generyczny.

Wynik powinien wyświetlać podsumowanie, a następnie rezultat walidacji:

Article: {title}
Valid: {true/false}

Na przykład dla danych wejściowych Rust Tips i true:

Article: Rust Tips
Valid: true

A dla danych wejściowych Breaking News i false:

Article: Breaking News
Valid: false

Otrzymasz dwa dane wejściowe: tytuł artykułu oraz informację, czy formularz jest wypełniony (parsuj jako bool).

Spróbuj swoich sił

mod processor;

use processor::{Summarize, Validate, process_items};
use std::io;

// TODO: Zdefiniuj publiczną strukturę Article z publicznym polem title (String)
// Wyprowadź Clone dla Article

// TODO: Zaimplementuj Summarize dla Article
// Metoda summary powinna zwracać "Article: {title}"

// TODO: Zdefiniuj publiczną strukturę Form z publicznym polem filled (bool)

// TODO: Zaimplementuj Validate dla Form
// Metoda validate powinna zwracać wartość filled

fn main() {
    let mut title = String::new();
    io::stdin().read_line(&mut title).expect("Failed to read line");
    let title = title.trim().to_string();

    let mut filled_input = String::new();
    io::stdin().read_line(&mut filled_input).expect("Failed to read line");
    let filled: bool = filled_input.trim().parse().expect("Failed to parse bool");

    // TODO: Utwórz Article z podanym title
    
    // TODO: Utwórz Form z podaną wartością filled
    
    // TODO: Wywołaj process_items z article i form
}
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