Menu
Coddy logo textTech

Сопоставление вариантов с данными

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

В предыдущем уроке вы использовали match внутри методов enum, чтобы обрабатывать разные варианты. Теперь давайте сосредоточимся на том, как match фактически извлекает данные, хранящиеся внутри этих вариантов: технике, называемой destructure.

Когда вы сопоставляете вариант перечисления, который содержит данные, вы можете связать эти данные с переменными прямо в шаблоне:

enum Event {
    Click { x: i32, y: i32 },
    KeyPress(char),
    Resize(u32, u32),
}

fn handle_event(event: Event) {
    match event {
        Event::Click { x, y } => {
            println!("Clicked at ({}, {})", x, y);
        }
        Event::KeyPress(key) => {
            println!("Key pressed: {}", key);
        }
        Event::Resize(width, height) => {
            println!("Resized to {}x{}", width, height);
        }
    }
}

Каждая ветвь извлекает данные по-разному в зависимости от структуры варианта. Для вариантов, похожих на структуры, используется { field_name }, чтобы извлечь именованные поля. Для вариантов-кортежей используются позиционные переменные, например (width, height).

Выбранные вами имена переменных становятся доступными внутри этой ветви match. Это удобно, потому что вы одновременно проверяете, какой вариант у вас есть, и получаете доступ к его полезной нагрузке.

Компилятор гарантирует, что вы handle каждый вариант, а извлечённые значения сразу готовы к использованию: дополнительные steps не нужны.

challenge icon

Задание

Легко

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

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

  • command.rs: Define публичный Command enum с тремя вариантами:
    • Say: holds одно сообщение String (синтаксис кортежа)
    • Move: holds named поля: direction (String) и steps (u32)
    • Calculate: holds два значения i32, представляющие числа для сложения (синтаксис кортежа)
    Затем Implement метод execute, который использует match, чтобы destructure каждый вариант и return String, описывающий выполненное действие.
  • main.rs: Подключите модуль command, создайте по одному экземпляру каждого варианта команды с использованием предоставленных inputs и вызовите метод execute для каждого, чтобы Print результаты.

Ваш метод execute должен destructure каждый вариант, чтобы получить доступ к его данным, и return сообщения в этих точных форматах:

  • Для Say: Saying: {message}
  • Для Move: Moving {steps} steps {direction}
  • Для Calculate: {a} + {b} = {sum}

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

Saying: {message}
Moving {steps} steps {direction}
{a} + {b} = {sum}

Например, если сообщение Say — "Hello world", перемещение составляет 5 steps в направлении "north", а для Calculate используются числа 10 и 25, вывод будет таким:

Saying: Hello world
Moving 5 steps north
10 + 25 = 35

Вы получите пять inputs: сообщение Say, направление, число steps и два числа для Calculate.

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

mod command;

use command::Command;

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

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

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

    let mut num1_input = String::new();
    std::io::stdin().read_line(&mut num1_input).expect("Failed to read line");
    let num1: i32 = num1_input.trim().parse().expect("Failed to parse num1");

    let mut num2_input = String::new();
    std::io::stdin().read_line(&mut num2_input).expect("Failed to read line");
    let num2: i32 = num2_input.trim().parse().expect("Failed to parse num2");

    // TODO: Создайте команду Say, используя say_message, и выполните её
    
    // TODO: Создайте команду Move, используя direction и steps, и выполните её
    
    // TODO: Создайте команду Calculate, используя num1 и num2, и выполните её
    
    // TODO: Выведите результаты выполнения каждой команды
}
quiz iconПроверьте себя

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

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

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