Menu
Coddy logo textTech

Setters

Fait partie de la section Object Oriented Programming du Journey Rust de Coddy — leçon 12 sur 61.

Les getters permettent au code externe de lire des données privées. Mais que se passe-t-il si vous devez leur permettre de les modifier ? C'est là que les méthodes setters interviennent — des méthodes publiques qui modifient les champs privés de manière contrôlée.

Un setter de base prend &mut self et une nouvelle valeur :

// wallet.rs
pub struct Wallet {
    balance: f64,
}

impl Wallet {
    pub fn new(initial: f64) -> Wallet {
        Self { balance: initial }
    }
    
    pub fn balance(&self) -> f64 {
        self.balance
    }
    
    pub fn set_balance(&mut self, amount: f64) {
        self.balance = amount;
    }
}

Contrairement aux getters, les setters en Rust utilisent généralement le préfixe set_ pour indiquer clairement qu'ils modifient les données. Le paramètre &mut self est essentiel — il accorde à la méthode la permission de modifier les champs de la structure.

Le véritable pouvoir des setters est la validation. Au lieu d'accepter aveuglément n'importe quelle valeur, vous pouvez imposer des règles :

pub fn set_balance(&mut self, amount: f64) {
    if amount >= 0.0 {
        self.balance = amount;
    }
    // Negative values are silently ignored
}

Désormais, le portefeuille se protège lui-même : peu importe la valeur que le code externe tente de définir, le solde ne peut jamais devenir négatif. C'est l'encapsulation en action : la structure contrôle ses propres invariants, et le code externe ne peut tout simplement pas la mettre dans un état invalide.

challenge icon

Défi

Facile

Construisons un système de thermostat qui démontre comment les setters peuvent appliquer des règles pour maintenir la validité des données. Votre thermostat aura un réglage de température qui ne peut être ajusté que dans une plage de sécurité.

Vous allez créer deux fichiers pour organiser votre code :

  • thermostat.rs : Définissez une structure Thermostat avec un champ privé temperature (i32). La structure doit être publique, mais le champ reste privé pour le protéger des valeurs invalides. Implémentez :
    • Un constructeur new qui prend une température initiale
    • Un getter temperature qui renvoie la température actuelle
    • Un setter set_temperature qui n'accepte que des valeurs comprises entre 10 et 30 (inclus). Si la valeur est en dehors de cette plage, la température doit rester inchangée.
  • main.rs : Importez votre module thermostat, créez un thermostat et démontrez la validation du setter en essayant de régler diverses températures et en affichant le résultat après chaque tentative.

Le setter doit ignorer silencieusement les valeurs invalides — aucun message d'erreur, gardez simplement la température actuelle inchangée lorsque quelqu'un essaie de la régler en dehors de la plage valide.

Votre sortie doit suivre ce format exact :

Initial: {temperature}
After setting to {attempted_value}: {temperature}
After setting to {attempted_value}: {temperature}

Par exemple, si vous créez un thermostat à 20, puis essayez de le régler à 25 (valide) et ensuite à 50 (invalide), la sortie serait :

Initial: 20
After setting to 25: 25
After setting to 50: 25

Vous recevrez trois entrées : la température initiale, la première température à tenter et la deuxième température à tenter.

Aide-mémoire

Les méthodes de type setter permettent au code externe de modifier des champs privés de manière contrôlée. Elles prennent &mut self pour obtenir la permission de modifier les données de la structure.

Syntaxe de base d'un setter :

pub fn set_balance(&mut self, amount: f64) {
    self.balance = amount;
}

Les setters en Rust utilisent généralement le préfixe set_ pour indiquer clairement qu'ils modifient des données.

Les setters permettent la validation pour appliquer des règles et maintenir l'intégrité des données :

pub fn set_balance(&mut self, amount: f64) {
    if amount >= 0.0 {
        self.balance = amount;
    }
    // Les valeurs invalides sont ignorées silencieusement
}

C'est l'encapsulation en action : la structure contrôle ses propres invariants, empêchant le code externe de la placer dans un état invalide.

Essayez vous-même

mod thermostat;

use thermostat::Thermostat;

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_temp: i32 = input1.trim().parse().expect("Invalid number");

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let first_attempt: i32 = input2.trim().parse().expect("Invalid number");

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let second_attempt: i32 = input3.trim().parse().expect("Invalid number");

    // TODO: Créer un thermostat avec la température initiale

    // TODO: Afficher la température initiale
    // Format: "Initial: {temperature}"

    // TODO: Tenter de régler la première température et afficher le résultat
    // Format: "After setting to {attempted_value}: {temperature}"

    // TODO: Tenter de régler la deuxième température et afficher le résultat
    // Format: "After setting to {attempted_value}: {temperature}"
}
quiz iconTestez-vous

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