Menu
Coddy logo textTech

Перечисления с данными

Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 14 из 61.

Базовые перечисления в Rust позволяют определить тип с фиксированным набором вариантов, например Direction::North или Status::Active. Но перечисления Rust гораздо мощнее. Каждый вариант может содержать собственные данные, что делает перечисления невероятно гибкими для моделирования сценариев из реального мира.

Рассмотрим систему обмена сообщениями, в которой разные типы сообщений содержат разную информацию. Текстовое сообщение содержит содержимое, команда Move — координаты, а сигнал завершения не содержит вообще ничего. В Rust можно представить всё это с помощью одного перечисления:

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(u8, u8, u8),
}

Each вариант имеет различную форму. Quit не содержит данных: это всего лишь сигнал.

Move использует синтаксис, похожий на синтаксис структур, с полями named. Write содержит единственное значение String, используя синтаксис кортежей. ChangeColor содержит три значения, представляющие компоненты RGB.

Создание экземпляров этих вариантов выглядит так:

let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("Hello"));
let m4 = Message::ChangeColor(255, 128, 0);

Преимущество этого подхода в том, что m1, m2, m3 и m4 имеют один и тот же тип: Message. Ты можешь хранить их в одной коллекции, передавать их одной и той же функции или возвращать любой вариант из одной функции. Перечисление объединяет различные формы данных под одним типом, сохраняя при этом конкретную информацию, необходимую каждому варианту.

challenge icon

Задание

Легко

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

Вы создадите два файла, чтобы организовать свой код:

  • notification.rs: Define общедоступный enum Notification с тремя вариантами:
    • Alert: holds одно значение String message (синтаксис кортежа)
    • Reminder: holds именованные поля: title (String) и minutes (u32)
    • Dismiss: holds no data, только сигнал
  • main.rs: Подключите модуль notification и создайте по одному экземпляру каждого варианта. Затем выведите информацию о каждом уведомлении, чтобы продемонстрировать, что все три варианта имеют один и тот же тип, но содержат разные данные.

При выводе используйте отладочное форматирование ({:?}), чтобы отобразить каждое уведомление. Вам потребуется вывести для вашего enum производный трейт Debug, чтобы его можно было печатать таким образом.

Ваш вывод должен содержать все три уведомления, каждое на своей строке:

Alert("{message}")
Reminder { title: "{title}", minutes: {minutes} }
Dismiss

Например, если значение alert message — "Server down", title напоминания — "Meeting", а значение 30 — это количество minutes, вывод будет таким:

Alert("Server down")
Reminder { title: "Meeting", minutes: 30 }
Dismiss

Вы получите три входных значения: alert message, title напоминания и значение reminder minutes.

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

mod notification;

use notification::Notification;

fn main() {
    // Читаем входные данные
    let mut alert_message = String::new();
    std::io::stdin().read_line(&mut alert_message).expect("Failed to read line");
    let alert_message = alert_message.trim().to_string();

    let mut reminder_title = String::new();
    std::io::stdin().read_line(&mut reminder_title).expect("Failed to read line");
    let reminder_title = reminder_title.trim().to_string();

    let mut minutes_input = String::new();
    std::io::stdin().read_line(&mut minutes_input).expect("Failed to read line");
    let reminder_minutes: u32 = minutes_input.trim().parse().expect("Failed to parse minutes");

    // TODO: Создать уведомление Alert, используя alert_message

    // TODO: Create a Reminder notification using reminder_title and reminder_minutes

    // TODO: Создать уведомление Dismiss

    // TODO: Вывести каждое уведомление, используя отладочное форматирование {:?}
    // Каждое уведомление должно быть выведено на своей строке
}
quiz iconПроверьте себя

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

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

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