Méthodes génériques
Fait partie de la section Programmation Orientée Objet du Journey Rust de Coddy. Leçon 25 sur 61.
Une structure générique peut contenir n’importe quel type, mais elle n’est pas très utile sans méthodes permettant d’interagir avec ses données. Pour définir des méthodes pour une structure générique, tu as besoin d’une syntaxe spéciale dans le bloc impl.
La clé consiste à déclarer le paramètre générique sur le impl lui-même :
struct Wrapper<T> {
value: T,
}
impl<T> Wrapper<T> {
fn get(&self) -> &T {
&self.value
}
}
Remarque le impl<T> avant Wrapper<T>. Cela indique à Rust que T est un paramètre de type générique pour l’ensemble du bloc d’implémentation. Sans cette déclaration, Rust chercherait un type concret nommé T et ne le trouverait pas.
La méthode get renvoie &T : une référence vers le type que contient le wrapper. Cela fonctionne que T soit un entier, une chaîne de caractères ou tout autre type :
let num_wrapper = Wrapper { value: 100 };
let text_wrapper = Wrapper { value: "Rust" };
println!("{}", num_wrapper.get()); // 100
println!("{}", text_wrapper.get()); // Rust
La même définition de méthode fonctionne pour les deux, car le type générique T s’adapte à chaque type concret lors de la compilation.
Défi
FacileÉtendons votre conteneur générique avec des méthodes ! Vous allez construire une structure Box (à ne pas confondre avec le Box standard de Rust) qui peut contenir n’importe quel type et fournit des méthodes pour interagir avec son contenu.
Vous allez organiser votre code sur deux fichiers :
mybox.rs: définissez une structure générique publique appeléeMyBox<T>avec un champ privécontentsde typeT. Implémentez des méthodes pour cette structure :- Une fonction associée
newqui crée un nouveauMyBoxavec la valeur fournie - Une méthode
peekqui renvoie une référence au contenu (en utilisant&self) - Une méthode
replacequi prend une nouvelle valeur et remplace le contenu actuel (en utilisant&mut self)
- Une fonction associée
main.rs: importez votre module et montrez que les méthodes génériques fonctionnent avec différents types. Vous créerez des boîtes, consulterez leur contenu et remplacerez des valeurs pour montrer les méthodes en action.
Souvenez-vous de la syntaxe essentielle pour implémenter des méthodes sur une structure générique : vous devez placer impl<T> avant MyBox<T> pour indiquer à Rust que T est un paramètre générique pour l’ensemble du bloc d’implémentation.
Dans votre fichier principal, montrez le fonctionnement de votre MyBox en :
- Créant une boîte avec un entier (première entrée, analysée comme
i32) - Consultant son contenu et en affichant la valeur
- Remplaçant le contenu par un nouvel entier (deuxième entrée, analysée comme
i32) - Consultant à nouveau le contenu pour afficher la valeur mise à jour
- Créant une deuxième boîte avec une chaîne de caractères (troisième entrée)
- Consultant le contenu de la boîte contenant la chaîne
Votre sortie doit respecter ce format :
Integer box contains: {value}
After replace: {value}
String box contains: {value}Par exemple, avec les entrées 10, 25 et Rust :
Integer box contains: 10
After replace: 25
String box contains: RustVous recevrez trois entrées : un entier initial, un entier de remplacement et une valeur de type chaîne de caractères.
Essayez vous-même
mod mybox;
use mybox::MyBox;
fn main() {
// Lire les entrées
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let initial_int: i32 = input1.trim().parse().expect("Invalid integer");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let replacement_int: i32 = input2.trim().parse().expect("Invalid integer");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let string_value = input3.trim().to_string();
// TODO: Créer un MyBox avec l'entier initial
// TODO: Peek at its contents and print: "Integer box contains: {value}"
// TODO: Remplacer le contenu par l'entier de remplacement
// TODO: Peek again and print: "After replace: {value}"
// TODO: Créer un second MyBox avec la valeur de chaîne
// TODO: Peek at the string box and print: "String box contains: {value}"
}
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