Menu
Coddy logo textTech

Il trait Drop

Fa parte della sezione Programmazione orientata agli oggetti del percorso Rust di Coddy. Lezione 56 di 61.

Quando un valore esce dal suo ambito in Rust, viene ripulito automaticamente. Ma cosa succede se devi eseguire del codice personalizzato in quel momento, come registrare un log, rilasciare una risorsa o inviare un messaggio finale? Il trait Drop ti permette di definire esattamente cosa succede quando la tua struct sta per essere distrutta.

Il trait Drop ha un unico metodo chiamato drop che accetta &mut self:

struct Connection {
    id: u32,
}

impl Drop for Connection {
    fn drop(&mut self) {
        println!("Connection {} closed.", self.id);
    }
}

Non chiami mai drop direttamente: Rust lo chiama automaticamente quando il valore esce dal suo ambito:

fn main() {
    let conn = Connection { id: 42 };
    println!("Using connection...");
}  // "Connection 42 closed." prints here automatically

L'output sarebbe:

Using connection...
Connection 42 closed.

Questa è la versione di Rust di un distruttore. Viene comunemente usata per le operazioni di pulizia: chiudere i gestori di file, disconnettersi dai server o liberare risorse che Rust non può gestire automaticamente. Il trait Drop garantisce che il codice di pulizia venga eseguito, anche se l'ambito termina a causa di un return anticipato.

challenge icon

Sfida

Facile

Costruiamo un sistema di gestione delle risorse che dimostri la pulizia automatica! Creerai una struct FileHandle che simula l'apertura e la chiusura dei file; quando l'handle esce dallo scope, annuncerà automaticamente che il file è stato chiuso.

Organizzerai il codice in due file:

  • file_handle.rs: Definisci una struct pubblica FileHandle con un campo pubblico filename (String). Implementa una funzione associata new che crea un FileHandle e stampa un messaggio quando il file viene "aperto". Poi implementa il trait Drop in modo che, quando l'handle viene eliminato, stampi un messaggio di chiusura.
  • main.rs: Includi il tuo modulo file_handle e crea una funzione chiamata process_file che accetta un filename, crea un FileHandle all'interno di uno scope locale e stampa un messaggio di elaborazione mentre il file è "aperto". L'implementazione di Drop verrà eseguita automaticamente quando termina lo scope. Chiama questa funzione con l'input fornito.

Quando viene creato un FileHandle, dovrebbe stampare:

Opening file: {filename}

Durante l'elaborazione (all'interno dello scope), stampa:

Processing {filename}...

Quando il FileHandle viene eliminato (al termine dello scope), dovrebbe stampare:

Closing file: {filename}

Per esempio, con l'input data.txt:

Opening file: data.txt
Processing data.txt...
Closing file: data.txt

E con l'input config.json:

Opening file: config.json
Processing config.json...
Closing file: config.json

Riceverai un input: la stringa del filename.

Provalo tu

mod file_handle;

use file_handle::FileHandle;

// TODO: Implementa la funzione process_file
// Deve:
// 1. Creare uno scope locale (usando le parentesi graffe {})
// 2. All'interno dello scope, creare un FileHandle usando FileHandle::new()
// 3. Stampare il messaggio di elaborazione: "Processing {filename}..."
// 4. Alla fine dello scope, Drop verrà chiamato automaticamente
fn process_file(filename: &str) {
    // TODO: Implementa questa funzione
}

fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let filename = input.trim();
    
    process_file(filename);
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Rust online