Lecții din modul (1/2)
Generice și funcții
Generice vă permit să scrieți cod flexibil, reutilizabil, evitând duplicarea logicii pentru diferite tipuri de date. În loc să definim mai multe funcții sau structuri pentru diferite tipuri (cum ar fi i32, f64 sau String), putem folosi un parametru de tip generic, reprezentat în mod convențional prin litera T.
Compilatorul Rust gestionează generice folosind un proces numit monomorfizare: în timpul compilării, generează o copie a codului generic pentru fiecare tip de beton care este efectiv utilizat. Aceasta înseamnă că nu există nicio suprasarcină de performanță la timpul de rulare.
Funcții generice
Pentru a defini o funcție generică, inserăm parametrul de tip <T> imediat după numele funcției și înaintea listei de argumente:
fn print_value<T: std::fmt::Debug>(value: T) {
println!("Value: {:?}", value);
}În funcțiile generice, putem folosi tipul generic T atât pentru tipurile de argument, cât și pentru tipurile de returnare:
fn identity<T>(value: T) -> T {
value
}Structuri generice
De asemenea, putem folosi parametrii de tip generic în interiorul structurilor (struct) pentru a defini câmpuri flexibile:
struct KeyValuePair<K, V> {
key: K,
value: V,
}
fn main() {
let pair = KeyValuePair {
key: String::from("age"),
value: 30,
};
}Într-un bloc impl pentru o structură generică, trebuie să declarăm parametrul de tip <T> imediat după cuvântul cheie impl pentru a indica că implementăm metode pe o structură generică:
struct Container<T> {
value: T,
}
impl<T> Container<T> {
fn new(value: T) -> Self {
Container { value }
}
fn value(&self) -> &T {
&self.value
}
}Încercați-l singur
Exercițiul 1: Structura punctuală
Definiți o structură generică numită Point<T> cu două câmpuri: x de tip T și y de tip T. În funcția principală, instanțiați un punct variabil care conține un Punct cu valori întregi x = 5 și y = 10, apoi tipăriți valoarea punct.x.
Afișează indiciu
Declarați structura folosind `struct Point<T> { x: T, y: T }`. Instanțiază-l în principal și folosește `point.x` pentru a-l imprima.
Soluție disponibilă după 3 încercări
Exercițiul 2: Inversarea unui tuplu cu swap
Scrieți o funcție generică numită swap<T> care acceptă un tuplu de două elemente (T, T) și returnează un nou tuplu (T, T) cu pozițiile lor inversate. În funcția principală, apelați funcția cu tuplu (1, 2) și imprimați rezultatul.
Afișează indiciu
Semnătura funcției trebuie să fie `fn swap<T>(pereche: (T, T)) -> (T, T)`. Returnează tuplu inversat cu `(pair.1, pair.0)`.
Soluție disponibilă după 3 încercări
Exercițiul 3: Structura containerului
Definiți o structură generică Container<T> care conține un câmp de valoare de tip T. Implementați un bloc generic impl pentru a defini o nouă metodă care acceptă o valoare de tip T și returnează o instanță a Container<T>.
Afișează indiciu
Folosiți `impl<T> Container<T>` pentru a implementa metoda asociată`fn new(valoare: T) -> Self { Container { value } }`.
Soluție disponibilă după 3 încercări