Сопоставление вариантов с данными
Часть раздела Объектно-ориентированное программирование путешествия по 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 не нужны.
Задание
ЛегкоДавайте создадим процессор команд, который обрабатывает разные типы пользовательских команд. Каждая команда содержит разные данные, а ваш процессор будет использовать сопоставление с образцом, чтобы извлекать эти данные и формировать подходящие ответы.
Вы создадите два файла, чтобы организовать код:
command.rs: Define публичныйCommandenum с тремя вариантами:Say: holds одно сообщениеString(синтаксис кортежа)Move: holds named поля:direction(String) иsteps(u32)Calculate: holds два значенияi32, представляющие числа для сложения (синтаксис кортежа)
execute, который используетmatch, чтобы destructure каждый вариант и returnString, описывающий выполненное действие.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: Выведите результаты выполнения каждой команды
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media PlayerПотренируйтесь самостоятельно: Онлайн-компилятор Rust