Множественные ограничения
Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 41 из 61.
Иногда одного ограничения трейта недостаточно. Вам может понадобиться тип generic, который может both выводиться на экран и предоставлять сводку. Rust позволяет требовать несколько трейтов, используя синтаксис +.
Вот как указать, что тип должен реализовывать два трейта:
use std::fmt::Display;
trait Summary {
fn summarize(&self) -> String;
}
fn announce<T: Display + Summary>(item: T) {
println!("Breaking news: {}", item);
println!("Summary: {}", item.summarize());
}
Ограничение типа T: Display + Summary означает: «T должен реализовывать оба трейта — Display и Summary». Внутри функции можно использовать возможности обоих трейтов: выводить данные с помощью {} (из Display) и вызывать summarize() (из Summary).
Вы можете объединить столько трейтов, сколько необходимо:
fn process<T: Display + Summary + Clone>(item: T) {
// Может печатать, суммировать И клонировать
}
Этот шаблон необходим, когда ваш function зависит от нескольких вариантов поведения. Вместо того чтобы принимать any тип и надеяться, что всё работает, вы явно объявляете, какие именно capabilities требуются, а компилятор проверяет это во время компиляции.
Задание
ЛегкоДавайте создадим систему проверки продуктов, которая требует от элементов нескольких capabilities! Вы создадите generic function, принимающую только типы, реализующие одновременно пользовательский трейт и стандартный трейт, демонстрируя, как синтаксис + объединяет несколько ограничений.
Вы организуете код в двух файлах:
product.rs: Define публичный трейтInspectableс method под названиемinspect, который принимает&selfи возвращаетString, содержащий сведения о проверке. Затем создайте публичную структуруGadgetс публичными полямиname(String) иserial(u32). Ваш Gadget должен реализовывать иInspectable(возвращаяInspecting: {name}), иstd::fmt::Display(форматируя как{name} (SN: {serial})). Наконец, создайте публичную generic function с именемfull_report, которая принимает любой типT, реализующий одновременноDisplayиInspectable. Эта function должна print две lines: сначала item с использованием форматировщика{}, затем result вызоваinspect().main.rs: Подключите свой модуль product и создайте экземплярGadget, используя предоставленные inputs. Вызовитеfull_reportсо своим gadget, чтобы показать, что он соответствует обоим требованиям трейтов.
Сила нескольких ограничений заключается в том, что ваша function full_report может использовать capabilities обоих трейтов, красиво отображая item И получая сведения о проверке — и всё это гарантируется во время компиляции.
Ваш вывод должен показывать и формат отображения, и result проверки:
{name} (SN: {serial})
Inspecting: {name}Например, с inputs Smartwatch и 98765:
Smartwatch (SN: 98765)
Inspecting: SmartwatchВы получите два inputs: имя gadget и серийный номер (разберите его как u32).
Попробуйте сами
mod product;
use product::{Gadget, full_report};
fn main() {
// Прочитать входные данные
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
let mut serial_input = String::new();
std::io::stdin().read_line(&mut serial_input).expect("Failed to read line");
let serial: u32 = serial_input.trim().parse().expect("Failed to parse serial");
// TODO: Создайте экземпляр Gadget с name и serial
// TODO: Вызовите full_report с вашим gadget
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media PlayerПотренируйтесь самостоятельно: Онлайн-компилятор Rust