Riduci il footprint del tuo codice Rust e aumenta la sua robustezza con tipi generici.

Ci sono sempre livelli di incertezza durante lo sviluppo di applicazioni, che possono portare a errori, specialmente se le tue funzioni accettano tipi specifici di argomenti. Per ridurre gli errori dovuti a incertezze, puoi utilizzare Generics. I generici forniscono funzionalità per la creazione di classi, funzioni e strutture di dati per lavorare con tipi diversi.

Utilizzando i generici, puoi creare e definire algoritmi e strutture di dati che possono operare su più tipi senza scrivere codice complesso e implementazioni separate per ogni tipo. I generici migliorano la riusabilità e l'efficienza del codice mantenendo la sicurezza dei tipi e le prestazioni.

Utilizzo di tipi generici in Rust

Il tipo generico di Rust può interagire con altri tipi di dati di Rust. Definirai i tipi generici con parentesi angolari (<>), seguiti da due o più parametri.

Ecco un generico definizione di struttura che accetta due parametri di tipo generico:

instagram viewer
structPunto {
// T e U sono parametri di tipo generico che saranno i campi x e y
// assume all'istanza
x: T,
si: tu,
}

Nel Punto strutturare, T, E U sono parametri di tipo generico.

È possibile sostituire i parametri di tipo generico con qualsiasi tipo di dati durante l'istanza:

fnprincipale() {
permettere mio_punto = Punto { x: Corda::da("Ciao"), y: Corda::da("mondo") };

stampa!(
"Il valore x di mio_punto è {} e il valore y è {}.",
mio_punto.x,
mio_punto.y
);
}

IL il mio punto variabile è un'istanza di Punto struct inizializzato con tipi stringa. Il compilatore Rust deduce i tipi concreti di T E U in base ai valori di istanziazione.

Limiti di tratto per tipi generici

I tipi generici di Rust possono utilizzare i limiti dei tratti per garantire la sicurezza dei tipi. I tratti sono raccolte di metodi che i tipi possono implementare per esibire determinati comportamenti definiti per il tratto.

I limiti dei tratti specificano che un tipo generico deve implementare uno o più tratti.

Ecco un esempio di una funzione generica che restituisce il maggiore di due valori con un tratto associato che garantisce che i tipi confrontati implementino il tratto:

// Maximum è una caratteristica che definisce un metodo per valutare il massimo di due
// tipi
trattoMassimo {
fnmax(se stesso, altro: Se stesso) -> Se stesso;
}

// Implementa il tratto `Maximum` per tutti i tipi che implementano il
// Tratto `PartialOrd`.
impParzialeOrd> Massimo per T {
fnmax(se stesso, altro: Se stesso) -> Se stesso {
// restituisce `self` se è maggiore di `other`; altrimenti, ritorna
// `altro.`
Sese stesso > altro {
se stesso
} altro {
altro
}
}
}

fnprincipale() {
permettere un = 5;
permettere b = 10;
permettere più grande = massimo:: max (a, b);
stampa!("Il valore più grande è {}", maggiore);
}

IL Massimo tratto ha un max metodo che restituisce il maggiore di due valori dello stesso tipo. Qualsiasi tipo che implementa il ParzialeOrd tratto implementa il Massimo tratto.

IL max metodo accetta due valori di Se stesso type: riferito al tipo che implementa il file Massimo tratto e confronta i valori.

IL principale La funzione confronta due variabili utilizzando il max metodo e stampa il più grande.

Vincoli per tipi generici

I vincoli sono simili ai limiti dei tratti, ma ti consentono di specificare requisiti aggiuntivi sui tipi che stai usando come parametri di tipo.

Se vuoi creare una funzione generica che accetti tipi per la conversione di stringhe, puoi usare un vincolo per garantire che il parametro type implementi un tratto.

// ToString è un tratto con un metodo di conversione di stringhe
trattoAccordare {
fnaccordare(&se stesso) -> Corda;
}

// to_string è una funzione generica che accetta un valore di qualsiasi tipo che
// implementa il tratto ToString
fnaccordareAccordare>(valore: T) -> Corda {
valore.alla_stringa()
}

IL accordare Il parametro value deve implementare il Accordare trait, che garantisce la possibilità di convertire i valori di tipo T stringere con il accordare metodo.

I tipi generici sono utili per lavorare con i tratti

I tipi generici di Rust sono potenti e ci sono aree di miglioramento. Un'area critica di interesse è il miglioramento delle prestazioni del codice generico. Attualmente, il sistema di tipi di Rust può imporre un sovraccarico al codice generico, rallentando le prestazioni.

I tipi generici sono utili per lavorare con i tratti. Utilizzando tipi generici, puoi creare oggetti tratto che funzionano con qualsiasi tipo che implementa un tratto per rendere i tuoi metodi più flessibili.