El Trait Drop
Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 56 de 61.
Cuando un valor sale de ámbito en Rust, se limpia automáticamente. Pero ¿qué ocurre si necesitas ejecutar código personalizado en ese momento, como registrar información, liberar un recurso o enviar un mensaje final? El trait Drop te permite definir exactamente qué sucede cuando tu estructura está a punto de destruirse.
El trait Drop tiene un único método llamado drop que toma &mut self:
struct Connection {
id: u32,
}
impl Drop for Connection {
fn drop(&mut self) {
println!("Connection {} closed.", self.id);
}
}
Nunca llamas a drop directamente: Rust lo llama automáticamente cuando el valor sale del ámbito:
fn main() {
let conn = Connection { id: 42 };
println!("Using connection...");
} // "Connection 42 closed." se imprime aquí automáticamente
La salida sería:
Using connection...
Connection 42 closed.
Esta es la versión de Rust de un destructor. Se usa comúnmente para tareas de limpieza: cerrar identificadores de archivo, desconectarse de servidores o liberar recursos que Rust no puede gestionar automáticamente. El rasgo Drop garantiza que tu código de limpieza se ejecute, incluso si el ámbito termina debido a un retorno anticipado.
Desafío
Fácil¡Vamos a construir un sistema de gestión de recursos que demuestre la limpieza automática! Crearás una struct FileHandle que simula la apertura y el cierre de archivos; cuando el handle salga del ámbito, anunciará automáticamente que el archivo ha sido cerrado.
Organizarás tu código en dos archivos:
file_handle.rs: Define una struct públicaFileHandlecon un campo públicofilename(String). Implementa una función asociadanewque crea un FileHandle e imprime un mensaje cuando el archivo es "abierto". Luego implementa el traitDroppara que, cuando el handle se descarta, imprima un mensaje de cierre.main.rs: Incorpora tu módulo file_handle y crea una función llamadaprocess_fileque toma un nombre de archivo, crea un FileHandle dentro de un ámbito local e imprime un mensaje de procesamiento mientras el archivo está "abierto". La implementación de Drop se ejecutará automáticamente cuando termine el ámbito. Llama a esta función con la entrada proporcionada.
Cuando se crea un FileHandle, debe imprimir:
Opening file: {filename}Mientras se procesa (dentro del ámbito), imprime:
Processing {filename}...Cuando el FileHandle se descarta (termina el ámbito), debe imprimir:
Closing file: {filename}Por ejemplo, con la entrada data.txt:
Opening file: data.txt
Processing data.txt...
Closing file: data.txtY con la entrada config.json:
Opening file: config.json
Processing config.json...
Closing file: config.jsonRecibirás una entrada: la cadena del nombre de archivo.
Pruébalo tú mismo
mod file_handle;
use file_handle::FileHandle;
// TODO: Implementa la función process_file
// Debería:
// 1. Crear un ámbito local (usando llaves {})
// 2. Dentro de ese ámbito, crear un FileHandle usando FileHandle::new()
// 3. Imprimir el mensaje de procesamiento: "Processing {filename}..."
// 4. Cuando el ámbito termine, Drop se llamará automáticamente
fn process_file(filename: &str) {
// TODO: Implementa esta función
}
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 lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Métodos y Comportamiento
Intro a Bloques de ImplementaciónEl Parámetro SelfMétodos MutablesFunciones AsociadasMúltiples Bloques de ImplementaciónEncadenamiento de MétodosResumen - Acciones de Rectángulo4Proyecto: Mascota virtual
Definir la mascotaAlimentar a la mascota7Traits estándar
El trait DebugEl trait DisplayClone y CopyTraits de igualdadResumen - Punto imprimible10Proyecto: Sistema de documentos
El Trait DrawComponente de texto2Encapsulamiento y módulos
Conceptos básicos de módulosLa palabra clave PublicCampos privadosGettersSettersRepaso - Casillero seguro5Genéricos
Estructuras genéricasMétodos genéricosMúltiples tipos genéricosFunciones genéricasResumen - Punto de coordenadas8Traits como límites
Sintaxis de límites de traitsLímites múltiplesLa cláusula whereRetornar tipos con traitsResumen: Impresora genérica11Patrones de diseño en Rust
Patrón NewtypeComposiciónEl Trait DropFrom e IntoResumen - Mock de Smart Pointer3Enums avanzados
Enums con datosMétodos en EnumsCoincidencia de variantes de datosEl Enum Option revisitadoResumen - Enum Shape6Definición de Traits
¿Qué es un Trait?Implementación de TraitsImplementaciones por defectoSobrescribir valores por defectoTraits con parámetrosResumen - Reproductor multimediaPractica por tu cuenta: Compilador de Rust online