Menu
Coddy logo textTech

A Trait Drop

Parte da seção Object Oriented Programming do Journey de Rust da Coddy — lição 56 de 61.

Quando um valor sai de escopo no Rust, ele é limpo automaticamente. Mas e se você precisar executar um código personalizado nesse momento — como registrar um log, liberar um recurso ou enviar uma mensagem final? A trait Drop permite que você defina exatamente o que acontece quando sua struct está prestes a ser destruída.

O trait Drop possui um único método chamado drop que recebe &mut self:

struct Connection {
    id: u32,
}

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

Você nunca chama drop diretamente — o Rust a chama automaticamente quando o valor sai de escopo:

fn main() {
    let conn = Connection { id: 42 };
    println!("Using connection...");
}  // "Connection 42 closed." imprime aqui automaticamente

A saída seria:

Using connection...
Connection 42 closed.

Esta é a versão do Rust de um destrutor. É comumente usado para tarefas de limpeza: fechar manipuladores de arquivos, desconectar de servidores ou liberar recursos que o Rust não consegue gerenciar automaticamente. A trait Drop garante que seu código de limpeza seja executado, mesmo que o escopo termine devido a um retorno antecipado.

challenge icon

Desafio

Fácil

Vamos construir um sistema de gerenciamento de recursos que demonstra a limpeza automática! Você criará uma struct FileHandle que simula a abertura e o fechamento de arquivos—quando o handle sai de escopo, ele anunciará automaticamente que o arquivo foi fechado.

Você organizará seu código em dois arquivos:

  • file_handle.rs: Defina uma struct FileHandle pública com um campo filename público (String). Implemente uma função associada new que cria um FileHandle e imprime uma mensagem quando o arquivo é "aberto". Em seguida, implemente a trait Drop para que, quando o handle for descartado, ele imprima uma mensagem de fechamento.
  • main.rs: Importe seu módulo file_handle e crie uma função chamada process_file que recebe um filename, cria um FileHandle dentro de um escopo local e imprime uma mensagem de processamento enquanto o arquivo está "aberto". A implementação de Drop será executada automaticamente quando o escopo terminar. Chame esta função com a entrada fornecida.

Quando um FileHandle for criado, ele deve imprimir:

Opening file: {filename}

Durante o processamento (dentro do escopo), imprima:

Processing {filename}...

Quando o FileHandle for descartado (fim do escopo), ele deve imprimir:

Closing file: {filename}

Por exemplo, com a entrada data.txt:

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

E com a entrada config.json:

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

Você receberá uma entrada: a string do filename.

Folha de consulta

A trait Drop permite que você defina código de limpeza personalizado que é executado automaticamente quando um valor sai de escopo.

A trait Drop possui um único método chamado drop que recebe &mut self:

struct Connection {
    id: u32,
}

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

Você nunca chama drop diretamente — o Rust o chama automaticamente quando o valor sai de escopo:

fn main() {
    let conn = Connection { id: 42 };
    println!("Using connection...");
}  // "Connection 42 closed." é impresso aqui automaticamente

A trait Drop é comumente usada para tarefas de limpeza, como fechar handles de arquivos, desconectar de servidores ou liberar recursos. Ela garante que seu código de limpeza seja executado, mesmo que o escopo termine devido a um retorno antecipado.

Experimente você mesmo

mod file_handle;

use file_handle::FileHandle;

// TODO: Implementar a função process_file
// Ela deve:
// 1. Criar um escopo local (usando chaves {})
// 2. Dentro desse escopo, criar um FileHandle usando FileHandle::new()
// 3. Imprimir a mensagem de processamento: "Processing {filename}..."
// 4. Quando o escopo terminar, o Drop será chamado automaticamente
fn process_file(filename: &str) {
    // TODO: Implementar esta função
}

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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming