Conoscere questi due concetti ti aiuterà a rafforzare la tua comprensione di come funziona Rust e di come puoi implementare le funzionalità OOP.

Tratti e vite sono componenti chiave di Rust. Puoi usare i tratti per definire comportamenti e capacità per i tipi da implementare. Sono molto versatili e consentono di scrivere codice più generico, ridurre la duplicazione e migliorare la manutenibilità.

Rust utilizza un altro meccanismo, le durate, per tenere traccia della proprietà delle variabili all'interno e all'esterno dell'ambito. In questo modo si evitano puntatori penzolanti durante la deallocazione delle variabili.

Insieme, i tratti e le durate aiutano a garantire la sicurezza del tipo, la sicurezza della memoria e l'affidabilità del codice.

Comprensione dei tratti in Rust

I tratti sono raccolte di metodi che altri tipi possono implementare. I tratti sono simili a interfacce in linguaggi come Java, Go e TypeScript ma più flessibili.

Userai il tratto parola chiave per definire i tratti in Rust, seguita da una dichiarazione delle firme del metodo.

instagram viewer
trattoMyTrait {
fnmio_metodo(&se stesso);
}

Il codice definisce un tratto denominato MyTrait con un mio_metodo metodo. IL &se stesso Il parametro indica che il metodo fa riferimento all'oggetto del tipo di implementazione come primo parametro.

Dopo aver definito un tratto, puoi implementarlo per i tuoi tipi personalizzati.

Ecco come puoi implementare un tratto per i tuoi tipi di struttura.

structPersona {
nome: Corda,
età: u32,
}

imp Informazioni per Persona {
fnriepilogo(&se stesso) {
stampa!("Mi chiamo {} e ho {} anni.", se stesso.nome, se stesso.età);
}
}

IL Persona struct implementa Informazioni, e puoi chiamare il riepilogo metodo sulle istanze di Persona struct.

fnprincipale(){
permettere giovanni = Persona { nome: Corda::da("John"), età: 30 };
giovanni.summary(); // Output: Mi chiamo John e ho 30 anni.
}

IL John variabile è un'istanza di Persona struct.

IL principale chiamate di funzione riepilogo che stampa un messaggio alla console:

Gli enum possono implementare i tratti. Ecco come puoi definire un enum con varianti che implementano il riepilogo metodo:

enumMyEnum {
Variante A,
VarianteB,
}

imp Informazioni per MioEnum {
fnriepilogo(&se stesso) {
incontrose stesso {
MyEnum:: VariantA => {
// implementazione per VariantA
}
MyEnum:: VariantB => {
// implementazione per VariantB
}
}
}
}

Utilizzo dei tratti per i parametri delle funzioni e i valori restituiti

È possibile utilizzare i tratti come parametri di funzione e valori restituiti. L'uso dei tratti come parametri di funzione è utile per scrivere codice generico con più tipi.

Ecco una funzione che accetta un parametro di qualsiasi tipo implementato Informazioni.

fnfare qualcosa(valore: T) {
valore.summary();
}

IL la sintassi lo specifica T deve attuare Informazioni. Puoi chiamare il riepilogo funzione con qualsiasi valore che implementa Informazioni.

Vite intere a Rust

Lo strumento di verifica del prestito di Rust analizza i programmi e garantisce un corretto utilizzo della memoria. A Ruggine, ogni valore ha un proprietario che è responsabile della deallocazione del valore. Quando le variabili prendono in prestito valori, prendono in prestito un riferimento al valore passato, ma il proprietario mantiene la proprietà.

Le durate sono un modo per garantire che i valori presi in prestito vengano utilizzati correttamente. Una durata è un'etichetta attaccata a un riferimento, che descrive per quanto tempo il riferimento è valido.

In Rust, puoi specificare una durata usando un'annotazione di apostrofo:

funzione<'UN>

Quando si crea un riferimento, al riferimento viene assegnata una durata che descrive per quanto tempo è valido. Se hai una funzione che accetta il riferimento a un valore, la durata deve essere più lunga della chiamata di funzione per garantire che il valore sia valido quando la funzione ritorna.

Ecco un esempio di specifica della durata in una funzione.

fnfare qualcosa<'UN>(x: &'UNio32) -> &'UNio32 {
X
}

fnprincipale() {
permettere x = 42;
permettere risultato = fai_qualcosa(&x);
stampa!("Il risultato è: {}", risultato);
}

Nel fare qualcosa funzione, il 'UN Il parametro lifetime indica che il riferimento a X è valido finché la funzione chiama. Il riferimento restituito è valido anche finché la funzione chiama.

IL principale La funzione stampa il risultato passando un riferimento a X variabile in principale funzione alla console.

La sintassi della durata può essere dettagliata, ma è essenziale per la sicurezza e la gestione della memoria. Le regole di elisione a tre durate forniscono linee guida che consentono a Rust di dedurre la durata dei riferimenti in determinate situazioni.

La regola della durata dell'input

La regola di durata dell'input specifica che se una funzione o un metodo accetta uno o più riferimenti come parametri di input, Rust presuppone che tutti i riferimenti abbiano la stessa durata.

In poche parole, la durata dei riferimenti di output sarà la stessa di quella dei riferimenti di input.

fnpiù lungo<'UN>(x: &'UNstr, y: &'UNstr) -> &'UNstr {
Se x.len() > y.len() { x } altro { e }
}

Nel più lungo funzione, Rust deduce che la durata del riferimento di output è la stessa del riferimento di input perché entrambi hanno lo stesso parametro di durata 'UN.

La regola della durata dell'input semplifica la scrittura di funzioni generiche che accettano più riferimenti come input.

La regola della durata dell'output

La regola di durata dell'output specifica che se una funzione o un metodo restituisce un riferimento, Rust presumerà che la durata del riferimento di output sia diversa dalla durata di qualsiasi riferimento di input.

fnprima parola<'UN>(s: &'UNstr) -> &'UNstr {
s.split_whitespace().next().unwrap()
}

In questa funzione, Rust deduce che la durata del riferimento di output è diversa dalla durata del riferimento di input perché il split_whitespace() Il metodo crea un riferimento di output che non accetta parametri di riferimento di input.

La regola dell'elisione delle vite

La regola di elisione delle durate si applica se una funzione o un metodo accetta un riferimento o un parametro di input e restituisce un riferimento. In tal caso, Rust presuppone che il riferimento di output abbia la stessa durata del riferimento di input.

fnpiù lungo<'UN>(x: &'UNstr, y: &str) -> &'UNstr {
Se x.len() > y.len() { x } altro { e }
}

In questa funzione, Rust deduce che la durata del riferimento di output è la stessa della durata del riferimento di input perché il riferimento di input si non ha parametri di durata. Rust elide il parametro della durata per si e presuppone che abbia la stessa durata di X.

Questa regola semplifica la scrittura di funzioni che accettano un riferimento di input e restituiscono un riferimento di output.

Tratti e vite

È possibile combinare tratti e durate per creare funzioni generiche che funzionano per i tipi che implementano una caratteristica e hanno una durata valida.

Ecco un tratto e una funzione che fa riferimento a un valore che implementa il tratto.

trattoAccordare {
fnaccordare(&se stesso) -> Corda;
}

fnaccordare<'UN, T: Accordare>(t: &'UN T) -> Corda {
t.a_stringa()
}

Qui, il parametro della durata 'UN assicura che il riferimento T è valido per la durata dell'oggetto a cui fa riferimento. Puoi usare il accordare funzione con tipi che implementano il Accordare tratto che ha una durata valida.

I tratti costituiscono la base per l'implementazione dei concetti OOP in Rust

I tratti ti consentono di definire i comportamenti. Sebbene Rust non sia un linguaggio di programmazione orientato agli oggetti (OOP), puoi utilizzare i tratti per implementare concetti OOP dall'incapsulamento all'ereditarietà, al polimorfismo e all'astrazione.

L'implementazione di questi concetti OOP con i tratti rende i tuoi programmi Rust scalabili, robusti, gestibili ed efficienti.