Реализации по умолчанию
Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 31 из 61.
До сих пор каждый метод trait, который мы определяли, был всего лишь сигнатурой: требованием без тела. Но что, если большинство типов, реализующих trait, использовали бы одну и ту же логику? Rust позволяет предоставить реализацию по умолчанию непосредственно в определении trait.
Вместо того чтобы заканчивать сигнатуру метода точкой с запятой, добавьте тело:
trait Greet {
fn greet(&self) -> String {
String::from("Hello there!")
}
}
Теперь любой тип, который реализует Greet, автоматически получает этот method, и при этом не нужно писать никакого кода в блоке impl:
struct Guest;
impl Greet for Guest {}
let visitor = Guest;
println!("{}", visitor.greet()); // Привет!
Пустой impl Greet for Guest {} допустим, потому что trait уже предоставляет поведение. struct просто «выбирает использование» trait и бесплатно получает default method.
Этот шаблон полезен, когда вы хотите определить общее поведение, которое работает в большинстве случаев. Типы, которым нужно что-то другое, могут переопределить default (об этом вы узнаете далее), а типам, которых устраивает стандартное поведение, не нужно повторять один и тот же код.
Задание
ЛегкоДавайте исследуем возможности default implementation, создав систему уведомлений! Ты создашь trait, который сразу предоставляет стандартное поведение, чтобы типы могли подключить его без написания повторяющегося кода.
Ты организуешь код в трёх файлах:
notifiable.rs: Define публичный traitNotifiableс methodnotify(&self) -> String, у которого есть default implementation. По умолчанию он должен возвращать"You have a new notification!". Любой тип, реализующий этот trait, автоматически получит такое поведение без необходимости что-либо писать в своём impl block.alerts.rs: Создай две простые публичные unit struct, которые реализуют твой trait:EmailAlert: реализуетNotifiableс пустым impl block (использует default)SystemAlert: также реализуетNotifiableс пустым impl block (использует default)
main.rs: Объедини свои модули и продемонстрируй, как оба типа alerts используют одинаковое default behavior. Создай экземпляры обеих struct и вызови их methodnotify.
В своём главном файле создай EmailAlert и SystemAlert, затем выведи их уведомления в отдельных строках.
Твой вывод должен быть таким:
You have a new notification!
You have a new notification!Обрати внимание, что оба типа создают идентичный вывод: в этом и заключается преимущество default implementations! Ни одной struct не пришлось писать код для method notify, но обе получили полностью работающее поведение уведомлений. На следующем уроке ты узнаешь, как переопределять эти default, когда типу требуется пользовательское поведение.
Попробуйте сами
mod notifiable;
mod alerts;
use notifiable::Notifiable;
use alerts::{EmailAlert, SystemAlert};
fn main() {
// TODO: Создать экземпляр EmailAlert
// TODO: Создать экземпляр SystemAlert
// TODO: Print the notification from EmailAlert
// TODO: Print the notification from SystemAlert
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media PlayerПотренируйтесь самостоятельно: Онлайн-компилятор Rust