Переопределение реализаций по умолчанию
Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 32 из 61.
Стандартные реализации удобны, но иногда типу требуется поведение, отличающееся от стандартного. В таких случаях можно override стандартную реализацию, предоставив собственную реализацию в блоке impl.
Просто определите метод с той же сигнатурой, но добавьте свою пользовательскую логику:
trait Greet {
fn greet(&self) -> String {
String::from("Hello there!")
}
}
struct Robot {
id: u32,
}
impl Greet for Robot {
fn greet(&self) -> String {
format!("BEEP BOOP. Unit {} online.", self.id)
}
}
Хотя Greet предоставляет метод greet по умолчанию, Robot полностью заменяет его собственной версией. Когда вы вызываете greet() у Robot, Rust использует пользовательскую реализацию:
let bot = Robot { id: 42 };
println!("{}", bot.greet()); // БИП БУП. Юнит 42 онлайн.
Это даёт вам гибкость: типам, которых устраивает default, не нужно ничего писать, а типы, которым требуется специализированное поведение, могут переопределить только те method, которые им нужны. Трейт по-прежнему гарантирует, что у каждого реализующего типа доступен method.
Задание
ЛегкоДавайте создадим систему уведомлений, в которой разные типы оповещений смогут настраивать свои сообщения! Вы создадите трейт с реализацией по умолчанию, затем один тип будет использовать значение по умолчанию, а другой — переопределять его с помощью собственного поведения.
Вы организуете код в трёх файлах:
notifiable.rs: Define публичный трейтNotifiableсnotify(&self) -> Stringmethod, у которого есть реализация по умолчанию, возвращающая"Alert: Something happened!".alerts.rs: Создайте две публичные структуры, которые по-разному implement ваш трейт:GenericAlert: unit-структура, использующая уведомление по умолчанию (пустой impl block)UrgentAlert: структура с публичным полемmessageтипа String, которая override значение по умолчанию и возвращает"URGENT: {message}", где{message}— её сохранённое сообщение
main.rs: Объедините модули и продемонстрируйте оба варианта поведения. СоздайтеGenericAlertиUrgentAlert, используя предоставленные input, затем выведите их уведомления.
Главная идея заключается в том, что GenericAlert бесплатно получает поведение по умолчанию, тогда как UrgentAlert предоставляет собственную специализированную версию, определяя method в своём impl block.
Ваш вывод должен соответствовать этому формату:
Alert: Something happened!
URGENT: {message}Например, при input Server is down!:
Alert: Something happened!
URGENT: Server is down!Вы получите один input: сообщение для срочного оповещения.
Попробуйте сами
mod notifiable;
mod alerts;
use alerts::{GenericAlert, UrgentAlert};
use notifiable::Notifiable;
fn main() {
// Считать ввод для сообщения срочного оповещения
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let message = input.trim().to_string();
// TODO: Создать экземпляр GenericAlert
// TODO: Создать экземпляр UrgentAlert с введённым сообщением
// TODO: Вывести уведомление от GenericAlert
// TODO: Вывести уведомление от UrgentAlert
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media PlayerПотренируйтесь самостоятельно: Онлайн-компилятор Rust