Ce face type (alias de tip și tip asociat)
type creează un alias: un al doilea nume pentru un tip existent. type Catalog = BTreeMap<String, Vec<u8>>; te scutește să scrii tipul lung de fiecare dată. Aliasul nu creează un tip nou: type Km = f64; și f64 sunt complet interschimbabile, deci compilatorul nu te oprește să aduni kilometri cu kilograme. Pentru un tip cu adevărat diferit, folosește un tuple struct (struct Km(f64);).
Un alias poate avea parametri generici. Modelul folosit de biblioteca standard este std::io::Result<T>, definit ca Result<T, std::io::Error>; la fel îți poți defini propriul Rezultat<T>.
În interiorul unui trait, type Nume; declară un tip asociat, pe care fiecare implementare îl alege. Exemplul clasic este Iterator, cu type Item;: fiecare iterator spune ce tip de elemente produce.
Exemple
Exemplul 1: Alias pentru un tip lung și pentru un Result
Catalog și Rezultat<T> scurtează semnăturile. Rezultat<f64> este exact Result<f64, String>.
use std::collections::BTreeMap;
type Catalog = BTreeMap<String, Vec<u8>>;
type Rezultat<T> = Result<T, String>;
fn media(catalog: &Catalog, elev: &str) -> Rezultat<f64> {
let note = catalog.get(elev).ok_or(format!("{elev} nu există"))?;
if note.is_empty() {
return Err(format!("{elev} nu are note"));
}
Ok(note.iter().map(|&n| n as f64).sum::<f64>() / note.len() as f64)
}
fn main() {
let mut catalog = Catalog::new();
catalog.insert("Ana".to_string(), vec![10, 9, 9]);
catalog.insert("Radu".to_string(), vec![]);
for elev in ["Ana", "Radu", "Dan"] {
match media(&catalog, elev) {
Ok(m) => println!("{elev}: {m:.2}"),
Err(e) => println!("eroare: {e}"),
}
}
}
Rezultat
Ana: 9.33
eroare: Radu nu are note
eroare: Dan nu există
Exemplul 2: Tip asociat într-un trait: Iterator
type Item = u64; spune că iteratorul Fibonacci produce numere u64. Odată implementat next, toate metodele lui Iterator (take, collect) funcționează.
struct Fibonacci {
a: u64,
b: u64,
}
impl Iterator for Fibonacci {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
let urmator = self.a;
self.a = self.b;
self.b += urmator;
Some(urmator)
}
}
fn main() {
let primele: Vec<u64> = Fibonacci { a: 0, b: 1 }.take(12).collect();
println!("{primele:?}");
}
Rezultat
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
Greșeli frecvente
- Crezi că
type Lei = f64;te protejează de amestecul cu euro. Aliasul este doar un nume; pentru verificare la compilare foloseștestruct Lei(f64);. - Scrii
typepentru a defini un tip nou cu câmpuri.typenu definește structuri; pentru asta existăstructșienum.
Comenzi înrudite
generics și where: Scrii o funcție sau un tip o singură dată, pentru orice tip T; limitele (T: Trait) spun ce trebuie să știe să facă T.trait: Definește un set de metode pe care un tip promite să le aibă. Seamănă cu interfețele din alte limbaje și stă la baza generics.struct: Definește un tip nou care grupează mai multe valori cu nume (câmpuri), de exemplu un elev cu nume, clasă și medie.operatorul ?: Pus după un Result sau Option: dă valoarea dacă totul e bine, altfel returnează imediat eroarea (sau None) din funcția curentă.