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.
Desafio
FácilVamos 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 structFileHandlepública com um campofilenamepúblico (String). Implemente uma função associadanewque cria um FileHandle e imprime uma mensagem quando o arquivo é "aberto". Em seguida, implemente a traitDroppara 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 chamadaprocess_fileque 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.txtE com a entrada config.json:
Opening file: config.json
Processing config.json...
Closing file: config.jsonVocê 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);
}
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
1Métodos e Comportamento
Introdução a Blocos de ImplementaçãoO Parâmetro SelfMétodos MutáveisFunções AssociadasMúltiplos Blocos de ImplementaçãoEncadeamento de MétodosRecapitulação - Ações de Retângulo4Projeto: Pet Virtual
Definindo o PetAlimentando o Pet7Traits Padrão
A Trait DebugA Trait DisplayClone e CopyTraits de IgualdadeRecapitulação - Ponto Imprimível10Projeto: Sistema de Documentos
A Trait DrawComponente de Texto2Encapsulamento e Módulos
Fundamentos de MódulosA Palavra-chave PublicCampos PrivadosGettersSettersRecapitulação - Cofre Seguro5Genéricos
Structs GenéricasMétodos GenéricosMúltiplos Tipos GenéricosFunções GenéricasRecapitulação - Ponto de Coordenada8Traits como Restrições
Sintaxe de Restrições de TraitRestrições MúltiplasA Cláusula WhereRetornando Tipos com TraitsRecapitulação - Impressora Genérica11Padrões de Projeto em Rust
Padrão NewtypeComposiçãoA Trait DropFrom e IntoRecapitulação - Mock de Smart Pointer3Enums Avançados
Enums com DadosMétodos em EnumsCorrespondência de Variantes de DadosO Enum Option RevisitadoRecapitulação - Enum Shape6Definição de Traits
O que é uma Trait?Implementando TraitsImplementações PadrãoSobrescrevendo PadrõesTraits com ParâmetrosRecapitulação - Media Player