Menu
Coddy logo textTech

Изменяемые методы

Часть раздела Object Oriented Programming путешествия по Rust на Coddy — урок 3 из 61.

Иногда методам нужно делать больше, чем просто читать данные — им нужно их изменять. Чтобы создать методы, которые могут изменять поля структуры, мы используем &mut self вместо &self.

Ключевое слово mut указывает на изменяемое заимствование, предоставляя методу разрешение изменять внутреннее состояние экземпляра:

struct Counter {
    value: i32,
}

impl Counter {
    fn increment(&mut self) {
        self.value += 1;
    }
    
    fn decrement(&mut self) {
        self.value -= 1;
    }
    
    fn get(&self) -> i32 {
        self.value
    }
}

Обратите внимание, что increment и decrement используют &mut self, потому что они изменяют value, в то время как get использует &self, так как он только считывает данные.

При вызове изменяемых методов сам экземпляр должен быть объявлен как изменяемый:

fn main() {
    let mut counter = Counter { value: 0 };
    
    counter.increment();
    counter.increment();
    println!("{}", counter.get()); // 2
    
    counter.decrement();
    println!("{}", counter.get()); // 1
}

Если вы забудете ключевое слово mut при создании экземпляра, Rust не позволит вам вызывать любые методы &mut self у него. Это гарантирует, что вы всегда будете знать, когда ваши данные могут измениться.

challenge icon

Задание

Легко

Создайте структуру BankAccount с одним полем: balance (i32).

Добавьте блок реализации для BankAccount с тремя методами:

  • deposit — принимает &mut self и amount: i32, добавляет сумму к балансу
  • withdraw — принимает &mut self и amount: i32, вычитает сумму из баланса
  • get_balance — принимает &self и возвращает текущий баланс как i32

Вы получите три входных значения:

  • Первая строка: начальный баланс (i32)
  • Вторая строка: сумма депозита (i32)
  • Третья строка: сумма снятия (i32)

Создайте изменяемый экземпляр BankAccount с начальным балансом, затем внесите указанную сумму депозита, снимите указанную сумму и выведите итоговый баланс.

Ожидаемый формат вывода:

{final_balance}

Шпаргалка

Методы, которые изменяют поля структуры, используют &mut self (изменяемое заимствование), в то время как методы, которые только читают данные, используют &self:

struct Counter {
    value: i32,
}

impl Counter {
    fn increment(&mut self) {
        self.value += 1;
    }
    
    fn decrement(&mut self) {
        self.value -= 1;
    }
    
    fn get(&self) -> i32 {
        self.value
    }
}

Чтобы вызывать изменяемые методы, экземпляр должен быть объявлен как изменяемый с помощью let mut:

let mut counter = Counter { value: 0 };

counter.increment();
counter.increment();
println!("{}", counter.get()); // 2

counter.decrement();
println!("{}", counter.get()); // 1

Без ключевого слова mut у экземпляра Rust запретит вызов любых методов с &mut self.

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

use std::io;

// TODO: Определите структуру BankAccount здесь


// TODO: Добавьте блок реализации для BankAccount с методами deposit, withdraw и get_balance


fn main() {
    let mut input = String::new();
    
    // Чтение начального баланса
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let initial_balance: i32 = input.trim().parse().expect("Invalid number");
    
    input.clear();
    
    // Чтение суммы депозита
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let deposit_amount: i32 = input.trim().parse().expect("Invalid number");
    
    input.clear();
    
    // Чтение суммы снятия
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let withdraw_amount: i32 = input.trim().parse().expect("Invalid number");
    
    // TODO: Создайте изменяемый экземпляр BankAccount с initial_balance
    // TODO: Вызовите deposit с deposit_amount
    // TODO: Вызовите withdraw с withdraw_amount
    // TODO: Выведите итоговый баланс, используя get_balance
}
quiz iconПроверьте себя

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

Все уроки раздела Object Oriented Programming