Menu
Coddy logo textTech

Множественные ограничения

Часть раздела Объектно-ориентированное программирование путешествия по 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 требуются, а компилятор проверяет это во время компиляции.

challenge icon

Задание

Легко

Давайте создадим систему проверки продуктов, которая требует от элементов нескольких 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).

REQUIRED OUTPUT FORMAT: [Your translated content here]

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

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

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

Все уроки раздела Объектно-ориентированное программирование

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