Menu
Coddy logo textTech

Setter

Fa parte della sezione Programmazione orientata agli oggetti del percorso Rust di Coddy. Lezione 12 di 61.

I getter permettono al codice esterno di leggere dati privati. Ma cosa succede se devi permettergli di modificarli? È qui che entrano in gioco i metodi setter: metodi pubblici che modificano i campi privati in modo controllato.

Un setter di base accetta &mut self e un nuovo valore:

// 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;
    }
}

A differenza dei getter, i setter di Rust usano tipicamente il prefisso set_ per indicare chiaramente che modificano i dati. Il parametro &mut self è essenziale. Consente al metodo di modificare i campi della struct.

Il vero potere dei setter è la convalida. Invece di accettare ciecamente qualsiasi valore, puoi applicare delle regole:

pub fn set_balance(&mut self, amount: f64) {
    if amount >= 0.0 {
        self.balance = amount;
    }
    // I valori negativi vengono ignorati senza alcun avviso
}

Ora il portafoglio si protegge da solo: qualunque valore il codice esterno provi a impostare, il saldo non può mai diventare negativo. Questa è l’incapsulamento in azione: la struct controlla i propri invarianti e il codice esterno semplicemente non può portarla in uno stato non valido.

challenge icon

Sfida

Facile

Costruiamo un sistema di termostato che dimostri come i setter possano applicare regole per mantenere validi i dati. Il tuo termostato avrà un'impostazione della temperatura che può essere regolata solo entro un intervallo sicuro.

Creerai due file per organizzare il codice:

  • thermostat.rs: definisci una struct Thermostat con un campo temperature privato (i32). La struct dovrebbe essere pubblica, ma il campo rimane privato per proteggerlo da valori non validi. Implementa:
    • Un costruttore new che accetta una temperatura iniziale
    • Un getter temperature che restituisce la temperatura corrente
    • Un setter set_temperature che accetta solo valori compresi tra 10 e 30 (inclusi). Se il valore è al di fuori di questo intervallo, la temperatura dovrebbe rimanere invariata.
  • main.rs: importa il modulo del termostato, crea un termostato e mostra la convalida del setter provando a impostare varie temperature e stampando il risultato dopo ogni tentativo.

Il setter dovrebbe ignorare silenziosamente i valori non validi: nessun messaggio di errore, semplicemente mantiene invariata la temperatura corrente quando qualcuno prova a impostarla al di fuori dell'intervallo valido.

L'output deve seguire esattamente questo formato:

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

Ad esempio, se crei un termostato a 20, poi provi a impostarlo a 25 (valido) e poi a 50 (non valido), l'output sarà:

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

Riceverai tre input: la temperatura iniziale, la prima temperatura da provare e la seconda temperatura da provare.

Provalo tu

mod thermostat;

use thermostat::Thermostat;

fn main() {
    // Lee las entradas
    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: Crea un termostato con la temperatura inicial

    // TODO: Imprime la temperatura inicial
    // Formato: "Initial: {temperature}"

    // TODO: Intenta establecer la primera temperatura e imprime el resultado
    // Formato: "After setting to {attempted_value}: {temperature}"

    // TODO: Intenta establecer la segunda temperatura e imprime el resultado
    // Formato: "After setting to {attempted_value}: {temperature}"
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Rust online