Menu
Coddy logo textTech

Struktury generyczne

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

Jak dotąd każda utworzona przez Ciebie struktura miała pola o konkretnych, określonych typach. Pet ma nazwę typu String, a Rectangle ma wymiary typu f64. A co, jeśli chcesz utworzyć strukturę, która może przechowywać dowolny typ danych?

Właśnie tutaj przydają się typy generyczne. Pozwalają pisać elastyczny, wielokrotnego użytku kod, który działa z wieloma typami. Zamiast wpisywać na sztywno konkretny typ, używasz symbolu zastępczego, zazwyczaj T, który zostaje zastąpiony konkretnym typem, gdy używasz struktury.

Oto prosty opakowujący typ strukturalny, który może przechowywać dowolny typ:

struct Wrapper<T> {
    value: T,
}

<T> po nazwie struktury deklaruje parametr typu generycznego. Wewnątrz struktury T pełni rolę zastępnika dla typu, którego faktycznie użyjesz. Gdy tworzysz instancję, Rust wywnioskuje konkretny typ:

let int_wrapper = Wrapper { value: 42 };        // T jest i32
let float_wrapper = Wrapper { value: 3.14 };    // T jest f64
let text_wrapper = Wrapper { value: "hello" };  // T jest &str

Każdy z nich jest innym typem konkretnym: Wrapper<i32>, Wrapper<f64> i Wrapper<&str>, ale wszystkie korzystają z tej samej definicji struktury. Dzięki temu nie trzeba pisać osobnych struktur IntWrapper, FloatWrapper i StringWrapper, które zasadniczo robią to samo.

Litera T to tylko konwencja (skrót od „Type”). Możesz użyć dowolnego prawidłowego identyfikatora, ale T jest standardem w Rust i większości innych języków obsługujących typy generyczne.

challenge icon

Wyzwanie

Łatwy

Zbudujmy generyczny kontener, który może przechowywać wartość dowolnego typu! Utworzysz strukturę Container, która pokazuje, jak generyczność sprawia, że kod jest elastyczny i można go ponownie wykorzystać.

Rozmieścisz kod w dwóch plikach:

  • container.rs: Zdefiniuj publiczną generyczną strukturę o nazwie Container<T> z jednym publicznym polem item typu T. Ten kontener powinien móc przechowywać dowolny typ: liczby całkowite, liczby zmiennoprzecinkowe, ciągi znaków lub cokolwiek innego.
  • main.rs: Dołącz moduł kontenera i pokaż jego elastyczność, tworząc kontenery przechowujące różne typy danych. Utworzysz trzy kontenery i wyświetlisz, co zawiera każdy z nich.

W pliku głównym utwórz następujące kontenery:

  1. Kontener przechowujący wartość całkowitą (pierwsze wejście, sparsowane jako i32)
  2. Kontener przechowujący wartość zmiennoprzecinkową (drugie wejście, sparsowane jako f64)
  3. Kontener przechowujący ciąg znaków (trzecie wejście, zachowane jako String)

Wynik powinien wyświetlać zawartość każdego kontenera w następującym formacie:

Integer container: {value}
Float container: {value}
String container: {value}

Na przykład dla wejść 42, 3.14 i hello:

Integer container: 42
Float container: 3.14
String container: hello

Zauważ, że ta sama definicja Container<T> działa dla wszystkich trzech różnych typów: na tym polega siła generyczności!

Otrzymasz trzy dane wejściowe: wartość całkowitą, wartość zmiennoprzecinkową i ciąg znaków.

Spróbuj swoich sił

mod container;

use container::Container;

fn main() {
    // Odczytaj trzy dane wejściowe
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let int_value: i32 = input1.trim().parse().expect("Failed to parse integer");

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let float_value: f64 = input2.trim().parse().expect("Failed to parse float");

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let string_value = input3.trim().to_string();

    // TODO: Utwórz trzy kontenery przy użyciu Container<T>
    // 1. Kontener na liczbę całkowitą przechowujący int_value
    // 2. Kontener na liczbę zmiennoprzecinkową przechowujący float_value
    // 3. Kontener na ciąg znaków przechowujący string_value

    // TODO: Wypisz zawartość każdego kontenera w wymaganym formacie
    // Integer container: {value}
    // Float container: {value}
    // String container: {value}
}
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