Blocs d'implémentation multiples
Fait partie de la section Object Oriented Programming du Journey Rust de Coddy — leçon 5 sur 61.
Rust vous permet de diviser les méthodes d'une structure en plusieurs blocs impl. Bien que tout puisse tenir dans un seul bloc, les séparer peut rendre votre code plus organisé et lisible.
Voici une structure dont les fonctionnalités sont réparties dans deux blocs d'implémentation :
struct BankAccount {
balance: f64,
}
// Constructeur et requêtes de base
impl BankAccount {
fn new(initial: f64) -> BankAccount {
BankAccount { balance: initial }
}
fn balance(&self) -> f64 {
self.balance
}
}
// Méthodes de transaction
impl BankAccount {
fn deposit(&mut self, amount: f64) {
self.balance += amount;
}
fn withdraw(&mut self, amount: f64) {
self.balance -= amount;
}
}
Les deux blocs fonctionnent ensemble de manière transparente — Rust les traite comme s'ils n'en faisaient qu'un. Vous pouvez appeler n'importe quelle méthode, quel que soit le bloc dans lequel elle est définie :
fn main() {
let mut account = BankAccount::new(100.0);
account.deposit(50.0);
println!("{}", account.balance()); // 150
}
Ce modèle devient particulièrement utile à mesure que vos structures s'agrandissent. Vous pourriez regrouper les constructeurs, séparer les méthodes en lecture seule des méthodes de mutation, ou organiser par fonctionnalité. Il n'y a pas de limite au nombre de blocs impl qu'une structure peut avoir.
Défi
FacileCréez une structure Player avec deux champs : name (String) et score (u32).
Organisez les méthodes de la structure dans deux blocs d'implémentation distincts :
Premier bloc impl — Constructeur et requête :
new— une fonction associée qui prend unname: Stringet renvoie unPlayeravec lescoreinitialisé à0get_score— prend&selfet renvoie le score actuel sous forme deu32
Deuxième bloc impl — Modifications du score :
add_points— prend&mut selfetpoints: u32, ajoute les points au scorereset_score— prend&mut selfet remet le score à0
Vous recevrez trois entrées :
- Première ligne : le nom du joueur (String)
- Deuxième ligne : les points à ajouter lors du premier tour (u32)
- Troisième ligne : les points à ajouter lors du deuxième tour (u32)
Créez un joueur en utilisant Player::new, ajoutez les points du premier tour, affichez le score, puis réinitialisez le score, ajoutez les points du deuxième tour et affichez le score final.
Format de sortie attendu :
{score_after_first_round}
{score_after_reset_and_second_round}Aide-mémoire
Rust permet de diviser les méthodes d'une structure sur plusieurs blocs impl pour une meilleure organisation :
struct BankAccount {
balance: f64,
}
// First impl block
impl BankAccount {
fn new(initial: f64) -> BankAccount {
BankAccount { balance: initial }
}
fn balance(&self) -> f64 {
self.balance
}
}
// Second impl block
impl BankAccount {
fn deposit(&mut self, amount: f64) {
self.balance += amount;
}
fn withdraw(&mut self, amount: f64) {
self.balance -= amount;
}
}
Toutes les méthodes provenant de différents blocs impl fonctionnent ensemble de manière transparente :
let mut account = BankAccount::new(100.0);
account.deposit(50.0);
println!("{}", account.balance()); // 150
Il n'y a pas de limite au nombre de blocs impl qu'une structure peut avoir. Ce modèle est utile pour regrouper des fonctionnalités liées, comme la séparation des constructeurs des méthodes de mutation.
Essayez vous-même
use std::io;
// TODO: Définir la structure Player avec les champs name (String) et score (u32)
// TODO: Premier bloc impl - Constructeur et méthodes de requête (new, get_score)
// TODO: Second bloc impl - Méthodes de modification du score (add_points, reset_score)
fn main() {
let mut input = String::new();
// Lire le nom du joueur
io::stdin().read_line(&mut input).expect("Failed to read line");
let name = input.trim().to_string();
// Lire les points du premier tour
input.clear();
io::stdin().read_line(&mut input).expect("Failed to read line");
let first_round: u32 = input.trim().parse().expect("Invalid number");
// Lire les points du deuxième tour
input.clear();
io::stdin().read_line(&mut input).expect("Failed to read line");
let second_round: u32 = input.trim().parse().expect("Invalid number");
// TODO: Créer un joueur en utilisant Player::new
// TODO: Ajouter les points du premier tour et afficher le score
// TODO: Réinitialiser le score
// TODO: Ajouter les points du deuxième tour et afficher le score final
}Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
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édia