Методы
Rust позволяет связывать функции с вашими новыми типами. Это делается через блок impl:
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[derive(Debug)]
struct CarRace {
name: String,
laps: Vec<i32>,
}
impl CarRace {
// Без получателя, статический метод
fn new(name: &str) -> Self {
Self { name: String::from(name), laps: Vec::new() }
}
// Эксклюзивный заимствованный доступ на чтение и запись к self
fn add_lap(&mut self, lap: i32) {
self.laps.push(lap);
}
// Разделяемый заимствованный доступ только на чтение к self
fn print_laps(&self) {
println!("Recorded {} laps for {}:", self.laps.len(), self.name);
for (idx, lap) in self.laps.iter().enumerate() {
println!("Lap {idx}: {lap} sec");
}
}
// Эксклюзивное владение self (рассмотрим позже)
fn finish(self) {
let total: i32 = self.laps.iter().sum();
println!("Race {} is finished, total lap time: {}", self.name, total);
}
}
fn main() {
let mut race = CarRace::new("Monaco Grand Prix");
race.add_lap(70);
race.add_lap(68);
race.print_laps();
race.add_lap(71);
race.print_laps();
race.finish();
// race.add_lap(42);
}
Аргументы self задают «получатель» (receiver) — объект, над которым работает метод. Для методов есть несколько распространённых видов получателей:
&self: заимствует объект у вызывающего кода через разделяемую неизменяемую ссылку. Объект можно использовать снова после этого.&mut self: заимствует объект у вызывающего кода через уникальную изменяемую ссылку. Объект можно использовать снова после этого.self: забирает владение объектом и перемещает его из вызывающего кода. Метод становится владельцем объекта. Объект будет освобождён (удалён из памяти) при возврате из метода, если только его владение явно не передано дальше. Полное владение автоматически не означает изменяемость.mut self: то же, что и выше, но метод может изменять объект.- Без получателя: это становится статическим методом структуры. Обычно так создают конструкторы, которые по соглашению называются
new.
This slide should take about 8 minutes.
Ключевые моменты:
- Может помочь введение методов через сравнение с функциями.
- Методы вызываются для экземпляра типа (например, структуры или перечисления); первый параметр представляет экземпляр как
self. - Разработчики могут использовать методы, чтобы воспользоваться синтаксисом получателя метода и лучше организовать код. Используя методы, мы держим весь код реализации в одном предсказуемом месте.
- Обратите внимание, что методы также можно вызывать как ассоциированные функции, явно передавая получатель, например
CarRace::add_lap(&mut race, 20).
- Методы вызываются для экземпляра типа (например, структуры или перечисления); первый параметр представляет экземпляр как
- Укажите на использование ключевого слова
self— получателя метода.- Покажите, что это сокращение для
self: Self, и, возможно, покажите, как можно использовать и имя структуры. - Объясните, что
Self— псевдоним типа, для которого написан блокimpl, и его можно использовать в других местах этого блока. - Покажите, что
selfиспользуется как и другие структуры, и что для отдельных полей можно использовать точечную нотацию. - Это хороший момент, чтобы показать, чем
&selfотличается отself, попробовав вызватьfinishдважды. - Помимо вариантов
self, получателями могут быть и специальные типы-обёртки, напримерBox<Self>.
- Покажите, что это сокращение для