Menu
Coddy logo textTech

Сеттеры

Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 12 из 61.

Getter-методы позволяют внешнему коду read private-данные. Но что, если нужно позволить ему их изменять? Здесь на помощь приходят методы setter: public-методы, которые контролируемым образом изменяют private-поля.

Базовый setter принимает &mut self и новое значение:

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

В отличие от getter, setter в Rust обычно используют префикс set_, чтобы ясно указать, что они изменяют данные. Параметр &mut self необходим. Он даёт методу разрешение изменять поля структуры.

Настоящая сила setter заключается в проверке. Вместо того чтобы бездумно принимать любое значение, вы можете применять правила:

pub fn set_balance(&mut self, amount: f64) {
    if amount >= 0.0 {
        self.balance = amount;
    }
    // Отрицательные значения молча игнорируются
}

Теперь кошелёк защищает себя: какое бы значение внешний код ни попытался установить, balance никогда не может стать отрицательным. Это инкапсуляция в действии: структура контролирует собственные инварианты, и внешний код просто не может привести её в недопустимое состояние.

challenge icon

Задание

Легко

Создадим систему термостата, демонстрирующую, как setter могут обеспечивать соблюдение правил для поддержания данных в допустимом состоянии. У вашего термостата будет настройка температуры, которую можно изменять только в безопасном диапазоне.

Вы создадите два файла, чтобы организовать код:

  • thermostat.rs: Define структуру Thermostat с private полем temperature (i32). Структура должна быть public, но поле остаётся private, чтобы защитить его от недопустимых значений. Implement:
    • конструктор new, принимающий initial температуру
    • getter temperature, который возвращает current температуру
    • setter set_temperature, который принимает только значения between 10 и 30 (inclusive). Если значение находится outside этого диапазона, температура должна остаться без изменений.
  • main.rs: Подключите модуль термостата, создайте термостат и продемонстрируйте проверку setter, пытаясь установить различные температуры и выводя result после каждой Attempt.

setter должен молча игнорировать недопустимые значения: никаких сообщений об ошибках — просто keep current температуру без изменений, когда кто-либо пытается установить её outside допустимого диапазона.

Ваш вывод должен точно соответствовать следующему формату:

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

Например, если вы создадите термостат с температурой 20, затем попытаетесь установить её на 25 (допустимое значение), а затем на 50 (недопустимое значение), вывод будет таким:

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

Вы получите три входных значения: initial температуру, первую температуру для Attempt и вторую температуру для Attempt.

Попробуйте сами

mod thermostat;

use thermostat::Thermostat;

fn main() {
    // Считать входные данные
    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: Создать термостат с начальной температурой

    // TODO: Вывести начальную температуру
    // Формат: "Initial: {temperature}"

    // TODO: Попытаться установить первую температуру и вывести результат
    // Format: "After setting to {attempted_value}: {temperature}"

    // TODO: Попытаться установить вторую температуру и вывести результат
    // Format: "After setting to {attempted_value}: {temperature}"
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Rust