Menu
Coddy logo textTech

Setters

Fait partie de la section Programmation Orientée Objet du Journey Rust de Coddy. Leçon 12 sur 61.

Les accesseurs permettent au code externe de lire des données privées. Mais que faire si vous devez lui permettre de les modifier ? C’est là qu’interviennent les méthodes mutatrices : des méthodes publiques qui modifient les champs privés de manière contrôlée.

Un setter basique 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 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 donne à la méthode la permission de modifier les champs de la structure.

La véritable puissance des setters réside dans la validation. Au lieu d’accepter aveuglément n’importe quelle valeur, tu peux imposer des règles :

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

Désormais, le portefeuille se protège lui-même : quelle que soit 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 placer dans un état invalide.

challenge icon

Défi

Facile

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

Vous créerez deux fichiers pour organiser votre code :

  • thermostat.rs : définissez une structure Thermostat avec un champ temperature privé (i32). La structure doit être publique, mais le champ reste privé afin de la protéger contre les 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 les 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 de thermostat, créez un thermostat et montrez la validation du setter en essayant de définir différentes températures et en affichant le résultat après chaque tentative.

Le setter doit ignorer silencieusement les valeurs invalides : aucun message d'erreur, conservez simplement la température actuelle lorsqu'une tentative est faite pour la définir en dehors de la plage valide.

Votre sortie doit respecter exactement le format suivant :

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 sur 25 (valide), puis sur 50 (invalide), la sortie sera :

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 à essayer et la deuxième température à essayer.

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 définir la première température et afficher le résultat
    // Format: "After setting to {attempted_value}: {temperature}"

    // TODO: Tenter de définir 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 Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Rust en ligne