Menu
Coddy logo textTech

Реализации по умолчанию

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

До сих пор каждый метод типажа, который мы определяли, был просто сигнатурой — требованием без тела. Но что, если большинство типов, реализующих типаж, будут использовать одну и ту же логику? Rust позволяет предоставить реализацию по умолчанию непосредственно в определении типажа.

Вместо того чтобы завершать сигнатуру метода точкой с запятой, вы добавляете тело:

trait Greet {
    fn greet(&self) -> String {
        String::from("Hello there!")
    }
}

Теперь любой тип, реализующий Greet, автоматически получает этот метод — без написания какого-либо кода в блоке impl:

struct Guest;

impl Greet for Guest {}

let visitor = Guest;
println!("{}", visitor.greet());  // Привет!

Пустая реализация impl Greet for Guest {} допустима, так как типаж уже предоставляет поведение. Структура просто «подписывается» на типаж и получает метод по умолчанию бесплатно.

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

challenge icon

Задание

Легко

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

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

  • notifiable.rs: Определите публичный трейт Notifiable с методом notify(&self) -> String, который имеет реализацию по умолчанию. По умолчанию он должен возвращать "You have a new notification!". Любой тип, реализующий этот трейт, автоматически получит это поведение без необходимости писать что-либо в своем блоке impl.
  • alerts.rs: Создайте две простые публичные unit-структуры, которые реализуют ваш трейт:
    • EmailAlert — реализует Notifiable с пустым блоком impl (использует реализацию по умолчанию)
    • SystemAlert — также реализует Notifiable с пустым блоком impl (использует реализацию по умолчанию)
    Обе структуры автоматически получат сообщение уведомления по умолчанию без написания вами тел методов!
  • main.rs: Объедините ваши модули и продемонстрируйте, как оба типа алертов разделяют одно и то же поведение по умолчанию. Создайте экземпляры обеих структур и вызовите их методы notify.

В вашем основном файле создайте EmailAlert и SystemAlert, затем выведите их уведомления на отдельных строках.

Ваш вывод должен быть таким:

You have a new notification!
You have a new notification!

Обратите внимание, что оба типа выдают одинаковый результат — в этом и заключается прелесть реализаций по умолчанию! Ни одной из структур не пришлось писать код для метода notify, но обе имеют полностью функциональное поведение уведомлений. В следующем уроке вы узнаете, как переопределять эти значения по умолчанию, когда типу требуется кастомное поведение.

Шпаргалка

Методы типажа могут иметь реализации по умолчанию, если предоставить тело метода вместо одной лишь сигнатуры:

trait Greet {
    fn greet(&self) -> String {
        String::from("Hello there!")
    }
}

Типы, реализующие этот типаж, автоматически получают поведение по умолчанию без написания какого-либо кода:

struct Guest;

impl Greet for Guest {}

let visitor = Guest;
println!("{}", visitor.greet());  // Hello there!

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

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

mod notifiable;
mod alerts;

use notifiable::Notifiable;
use alerts::{EmailAlert, SystemAlert};

fn main() {
    // TODO: Создать экземпляр EmailAlert
    
    // TODO: Создать экземпляр SystemAlert
    
    // TODO: Вывести уведомление от EmailAlert
    
    // TODO: Вывести уведомление от SystemAlert
}
quiz iconПроверьте себя

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

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