Menu
Coddy logo textTech

Переопределение реализаций по умолчанию

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

Реализации по умолчанию удобны, но иногда типу требуется поведение, отличное от стандартного. В таких случаях вы можете переопределить поведение по умолчанию, предоставив собственную реализацию в блоке 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 в сети.

Это дает вам гибкость — типам, которых устраивает поведение по умолчанию, не нужно ничего писать, в то время как типы, которым требуется специализированное поведение, могут переопределить только те методы, которые им важны. Трейт по-прежнему гарантирует, что у каждого реализующего типа этот метод будет доступен.

challenge icon

Задание

Легко

Давайте создадим систему уведомлений, в которой различные типы оповещений могут настраивать свои сообщения! Вы создадите трейт с реализацией по умолчанию, а затем сделаете так, чтобы один тип использовал поведение по умолчанию, в то время как другой переопределял его своим собственным поведением.

Вы организуете свой код в трех файлах:

  • notifiable.rs: Определите публичный трейт Notifiable с методом notify(&self) -> String, который имеет реализацию по умолчанию, возвращающую "Alert: Something happened!".
  • alerts.rs: Создайте две публичные структуры, которые по-разному реализуют ваш трейт:
    • GenericAlert — юнит-структура, использующая уведомление по умолчанию (пустой блок impl)
    • UrgentAlert — структура с публичным полем message (String), которая переопределяет поведение по умолчанию, возвращая "URGENT: {message}", где {message} — это сохраненное в ней сообщение
  • main.rs: Объедините ваши модули и продемонстрируйте оба варианта поведения. Создайте GenericAlert и UrgentAlert, используя предоставленные входные данные, а затем выведите их уведомления.

Ключевая идея здесь заключается в том, что GenericAlert получает готовое поведение по умолчанию, в то время как UrgentAlert предоставляет свою специализированную версию, определяя метод в своем блоке impl.

Ваш вывод должен соответствовать следующему формату:

Alert: Something happened!
URGENT: {message}

Например, при входных данных Server is down!:

Alert: Something happened!
URGENT: Server is down!

Вы получите одни входные данные: сообщение для срочного оповещения (urgent alert).

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

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
}
quiz iconПроверьте себя

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

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

Потренируйтесь самостоятельно: Онлайн-компилятор Rust