Изменяемые методы
Часть раздела 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 у него. Это гарантирует, что вы всегда будете знать, когда ваши данные могут измениться.
Задание
ЛегкоСоздайте структуру 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
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Object Oriented Programming
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media Player