Menu
Coddy logo textTech

Методы в перечислениях

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

Как и структуры, enum могут иметь method, определённые в блоках impl. Это позволяет напрямую прикреплять поведение к вашему типу enum, упрощая работу с различными variants через единый интерфейс.

Вот как добавить метод в перечисление Message из предыдущего урока:

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

impl Message {
    fn describe(&self) -> String {
        match self {
            Message::Quit => String::from("Quit signal"),
            Message::Move { x, y } => format!("Move to ({}, {})", x, y),
            Message::Write(text) => format!("Message: {}", text),
        }
    }
}

Блок impl Message работает точно так же, как и для структур. Метод принимает &self, чтобы получить доступ к экземпляру перечисления. Внутри метода вы используете match, чтобы определить, с каким вариантом работаете, и вернуть подходящий результат.

Вызов метода выглядит одинаково независимо от того, какой variant у вас есть:

fn main() {
    let m1 = Message::Quit;
    let m2 = Message::Move { x: 10, y: 20 };
    
    println!("{}", m1.describe());  // Сигнал выхода
    println!("{}", m2.describe());  // Перемещение в (10, 20)
}

Этот шаблон эффективен, потому что вызывающему коду не нужно знать, какой variant у него есть. Он просто вызывает method, а enum обрабатывает всё остальное внутри. Поведение меняется в зависимости от variant, но интерфейс остаётся неизменным.

challenge icon

Задание

Легко

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

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

  • traffic.rs: определите публичный TrafficLight enum с тремя вариантами:
    • Red: содержит u32, представляющий количество секунд ожидания
    • Yellow: содержит u32, представляющий количество секунд ожидания
    • Green: содержит u32, представляющий количество секунд движения
    Затем реализуйте метод status, который возвращает String с описанием сигнала. Используйте match внутри метода, чтобы обработать каждый вариант и включить длительность в сообщение.
  • main.rs: подключите модуль traffic, создайте экземпляры каждого варианта сигнала и вызовите метод status для каждого из них, чтобы вывести описания.

Метод status должен возвращать сообщения в следующих точных форматах:

  • Для Red: Stop for {seconds} seconds
  • Для Yellow: Caution for {seconds} seconds
  • Для Green: Go for {seconds} seconds

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

Stop for {seconds} seconds
Caution for {seconds} seconds
Go for {seconds} seconds

Например, если длительность красного сигнала составляет 30 секунд, жёлтого — 5 секунд, а зелёного — 25 секунд, вывод будет таким:

Stop for 30 seconds
Caution for 5 seconds
Go for 25 seconds

Вы получите три входных значения: длительность красного сигнала, длительность жёлтого сигнала и длительность зелёного сигнала.

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

mod traffic;

use traffic::TrafficLight;

fn main() {
    // Читаем ввод для длительностей
    let mut red_input = String::new();
    std::io::stdin().read_line(&mut red_input).expect("Failed to read line");
    let red_duration: u32 = red_input.trim().parse().expect("Invalid number");

    let mut yellow_input = String::new();
    std::io::stdin().read_line(&mut yellow_input).expect("Failed to read line");
    let yellow_duration: u32 = yellow_input.trim().parse().expect("Invalid number");

    let mut green_input = String::new();
    std::io::stdin().read_line(&mut green_input).expect("Failed to read line");
    let green_duration: u32 = green_input.trim().parse().expect("Invalid number");

    // TODO: Создать экземпляры каждого варианта TrafficLight с введёнными длительностями

    // TODO: Вызвать метод status у каждого светофора и вывести результат
}
quiz iconПроверьте себя

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

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

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