Реализация трейтов
Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 30 из 61.
Теперь, когда вы знаете, как определить trait, давайте посмотрим, как сделать так, чтобы структура выполняла этот контракт. Реализация trait связывает абстрактное требование с конкретным поведением.
Синтаксис использует impl TraitName for StructName:
trait Speak {
fn speak(&self) -> String;
}
struct Dog {
name: String,
}
impl Speak for Dog {
fn speak(&self) -> String {
format!("{} says: Woof!", self.name)
}
}
Блок impl Speak for Dog сообщает Rust, что Dog реализует трейт Speak. Внутри него вы указываете фактическое тело метода. Здесь вы определяете, как говорит собака.
Мощь трейтов становится очевидной, когда несколько типов реализуют один и тот же трейт:
struct Cat {
name: String,
}
impl Speak for Cat {
fn speak(&self) -> String {
format!("{} says: Meow!", self.name)
}
}
И Dog, и Cat теперь обладают возможностью Speak, но каждый из них предоставляет собственную уникальную реализацию. Вы можете вызвать .speak() для любого из этих типов:
let dog = Dog { name: String::from("Rex") };
let cat = Cat { name: String::from("Whiskers") };
println!("{}", dog.speak()); // Rex говорит: Гав!
println!("{}", cat.speak()); // Whiskers говорит: Мяу!
Это основа полиморфизма в Rust: разные типы, один и тот же интерфейс, уникальное поведение.
Задание
ЛегкоДавайте воплотим трейты в жизнь, реализовав их для разных типов! Вы создадите трейт Describable и реализуете его для двух разных структур, каждая из которых будет предоставлять собственное уникальное описание.
Вы организуете код в трёх файлах:
describable.rs: Определите публичный трейтDescribableс методомdescribe(&self) -> String.items.rs: Создайте две публичные структуры, реализующие ваш трейт:Bookс публичным полемtitle(String)Movieс публичным полемname(String)
Describableв собственном уникальном формате описания.main.rs: Объедините модули, создайте экземпляры обеих структур и вызовите их методыdescribe, чтобы показать, как один и тот же трейт создаёт разные результаты для разных типов.
Ваш Book должен описывать себя как Book: {title}, а ваш Movie — как Film: {name}. Обратите внимание, как каждый тип выполняет один и тот же контракт, но обладает собственным поведением!
В основном файле создайте книгу и фильм, используя два предоставленных входных значения, а затем выведите их описания в отдельных строках.
Ваш вывод должен соответствовать следующему формату:
Book: {title}
Film: {name}Например, для входных значений 1984 и Inception:
Book: 1984
Film: InceptionВы получите два входных значения: название книги и название фильма.
Попробуйте сами
mod describable;
mod items;
use describable::Describable;
use items::{Book, Movie};
fn main() {
// Читаем входные данные
let mut title = String::new();
std::io::stdin().read_line(&mut title).expect("Failed to read line");
let title = title.trim().to_string();
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
// TODO: Создать экземпляр Book с title
// TODO: Создать экземпляр Movie с name
// TODO: Вывести описание книги
// TODO: Вывести описание фильма
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media PlayerПотренируйтесь самостоятельно: Онлайн-компилятор Rust