Menu
Coddy logo textTech

Setters

Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 12 de 61.

Los getters permiten que el código externo lea datos privados. Pero ¿qué ocurre si necesitas permitirle cambiarlos? Ahí es donde entran los métodos setter: métodos públicos que modifican campos privados de forma controlada.

Un setter básico acepta &mut self y un nuevo valor:

// 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 diferencia de los getters, los setters de Rust suelen usar el prefijo set_ para indicar claramente que modifican datos. El parámetro &mut self es esencial. Concede al método permiso para cambiar los campos de la estructura.

El verdadero poder de los setters es la validación. En lugar de aceptar ciegamente cualquier valor, puedes hacer cumplir reglas:

pub fn set_balance(&mut self, amount: f64) {
    if amount >= 0.0 {
        self.balance = amount;
    }
    // Los valores negativos se ignoran silenciosamente
}

Ahora la billetera se protege a sí misma: sin importar qué valor intente establecer el código externo, el saldo nunca puede ser negativo. Esto es la encapsulación en acción: la estructura controla sus propias invariantes, y el código externo simplemente no puede hacer que adopte un estado no válido.

challenge icon

Desafío

Fácil

Construyamos un sistema de termostato que demuestre cómo los setters pueden aplicar reglas para mantener los datos válidos. Tu termostato tendrá un ajuste de temperatura que solo se podrá modificar dentro de un rango seguro.

Crearás dos archivos para organizar tu código:

  • thermostat.rs: Define una estructura Thermostat con un campo temperature privado (i32). La estructura debe ser pública, pero el campo debe permanecer privado para protegerlo de valores no válidos. Implementa:
    • Un constructor new que reciba una temperatura inicial
    • Un getter temperature que devuelva la temperatura actual
    • Un setter set_temperature que solo acepte valores entre 10 y 30 (inclusive). Si el valor está fuera de este rango, la temperatura debe permanecer sin cambios.
  • main.rs: Incluye tu módulo del termostato, crea un termostato y demuestra la validación del setter intentando establecer varias temperaturas e imprimiendo el resultado después de cada intento.

El setter debe ignorar silenciosamente los valores no válidos: sin mensajes de error, simplemente debe mantener la temperatura actual sin cambios cuando alguien intente establecerla fuera del rango válido.

Tu salida debe seguir exactamente este formato:

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

Por ejemplo, si creas un termostato a 20, después intentas establecerlo en 25 (válido) y después en 50 (no válido), la salida sería:

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

Recibirás tres entradas: la temperatura inicial, la primera temperatura que se intentará establecer y la segunda temperatura que se intentará establecer.

Pruébalo tú mismo

mod thermostat;

use thermostat::Thermostat;

fn main() {
    // Leer 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
    // Format: "After setting to {attempted_value}: {temperature}"

    // TODO: Intenta establecer la segunda temperatura e imprime el resultado
    // Format: "After setting to {attempted_value}: {temperature}"
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Rust online