Le trait Drop
Fait partie de la section Programmation Orientée Objet du Journey Rust de Coddy. Leçon 56 sur 61.
Lorsqu’une valeur sort de sa portée en Rust, elle est automatiquement nettoyée. Mais que faire si vous devez exécuter du code personnalisé à ce moment-là, comme consigner une information, libérer une ressource ou envoyer un message final ? Le trait Drop vous permet de définir exactement ce qui se passe lorsque votre structure est sur le point d’être détruite.
Le trait Drop possède une seule méthode appelée drop qui prend &mut self :
struct Connection {
id: u32,
}
impl Drop for Connection {
fn drop(&mut self) {
println!("Connection {} closed.", self.id);
}
}
Vous n’appelez jamais drop directement : Rust l’appelle automatiquement lorsque la valeur sort de sa portée :
fn main() {
let conn = Connection { id: 42 };
println!("Using connection...");
} // "Connection 42 closed." s'affiche ici automatiquement
La sortie serait :
Using connection...
Connection 42 closed.
C'est la version de Rust d'un destructeur. Il est couramment utilisé pour les tâches de nettoyage : fermer des descripteurs de fichiers, se déconnecter des serveurs ou libérer des ressources que Rust ne peut pas gérer automatiquement. Le trait Drop garantit que votre code de nettoyage s'exécute, même si la portée se termine en raison d'un retour anticipé.
Défi
FacileConstruisons un système de gestion des ressources qui illustre le nettoyage automatique ! Vous allez créer une structure FileHandle qui simule l’ouverture et la fermeture de fichiers ; lorsque le handle sort de sa portée, il annoncera automatiquement que le fichier a été fermé.
Vous allez organiser votre code sur deux fichiers :
file_handle.rs: Définissez une structure publiqueFileHandleavec un champ publicfilename(String). Implémentez une fonction associéenewqui crée un FileHandle et affiche un message lorsque le fichier est « ouvert ». Implémentez ensuite le traitDropafin que, lorsque le handle est supprimé, un message de fermeture soit affiché.main.rs: Importez votre module file_handle et créez une fonction appeléeprocess_filequi prend un nom de fichier, crée un FileHandle dans une portée locale et affiche un message de traitement pendant que le fichier est « ouvert ». L’implémentation de Drop s’exécutera automatiquement lorsque la portée se terminera. Appelez cette fonction avec l’entrée fournie.
Lorsqu’un FileHandle est créé, il doit afficher :
Opening file: {filename}Pendant le traitement (à l’intérieur de la portée), affichez :
Processing {filename}...Lorsque le FileHandle est supprimé (à la fin de la portée), il doit afficher :
Closing file: {filename}Par exemple, avec l’entrée data.txt :
Opening file: data.txt
Processing data.txt...
Closing file: data.txtEt avec l’entrée config.json :
Opening file: config.json
Processing config.json...
Closing file: config.jsonVous recevrez une entrée : la chaîne correspondant au nom du fichier.
Essayez vous-même
mod file_handle;
use file_handle::FileHandle;
// TODO: Implémentez la fonction process_file
// Elle devrait :
// 1. Créer une portée locale (en utilisant des accolades {})
// 2. À l'intérieur de cette portée, créer un FileHandle en utilisant FileHandle::new()
// 3. Afficher le message de traitement : "Processing {filename}..."
// 4. Lorsque la portée se termine, Drop sera automatiquement appelé
fn process_file(filename: &str) {
// TODO: Implémentez cette fonction
}
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);
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Méthodes et comportement
Introduction aux blocs d'implémentationLe paramètre SelfMéthodes mutablesFonctions associéesBlocs d'implémentation multiplesChaînage de méthodesRécapitulatif - Actions sur le rectangle4Projet : Animal virtuel
Définir l'animalNourrir l'animal7Traits standards
Le trait DebugLe trait DisplayClone et CopyLes traits d'égalitéRécapitulatif - Point affichable10Projet : Système de documents
Le trait DrawComposant texte2Encapsulation et modules
Bases des modulesLe mot-clé publicChamps privésGettersSettersRécapitulatif - Casier sécurisé5Généricité
Structures génériquesMéthodes génériquesPlusieurs types génériquesFonctions génériquesRécapitulatif - Point de coordonnées8Les Traits comme contraintes
Syntaxe des contraintes de traitContraintes multiplesLa clause whereRetourner des types avec des traitsRécapitulatif - Afficheur générique11Design Patterns en Rust
Le pattern NewtypeCompositionLe trait DropFrom et IntoRécapitulatif - Mock de Smart Pointer3Enums avancées
Enums avec donnéesMéthodes sur les EnumsMatching des variantes de donnéesL'Enum Option revisitéeRécapitulatif - Enum Shape6Définition des Traits
Qu'est-ce qu'un Trait ?Implémenter des TraitsImplémentations par défautRedéfinir les comportements par défautTraits avec paramètresRécapitulatif - Lecteur multimédiaEntraînez-vous par vous-même : Compilateur Rust en ligne