匹配数据变体
本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 16 课,共 61 课。
在上一课中,你在枚举方法里使用了 match 来处理不同的变体。现在,我们来看看 match 是如何提取这些变体中存储的数据的:这项技术称为解构。
匹配包含数据的枚举变体时,你可以直接在模式中将数据绑定到变量:
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)。
你选择的变量名会在对应的匹配分支中可用。这很实用,因为你可以同时检查自己拥有哪种变体,并且访问它携带的数据。
编译器会确保你处理每个变体,提取出的值可以立即使用,无需额外步骤。
挑战
简单我们来构建一个命令处理器,用来处理不同类型的用户命令。每个命令携带不同的数据,你的处理器会使用模式匹配提取这些数据,并生成相应的响应。
你将创建两个文件来组织代码:
command.rs:定义一个公共的Command枚举,包含三个变体:Say:保存一条String消息(元组语法)Move:保存命名字段:direction(String)和steps(u32)Calculate:保存两个表示待相加数字的i32值(元组语法)
execute方法,使用match解构每个变体,并返回描述所执行操作的String。main.rs:引入你的命令模块,使用提供的输入创建每种命令变体的一个实例,并对每个实例调用execute方法来打印结果。
你的 execute 方法应解构每个变体以访问其中的数据,并按照以下确切格式返回消息:
- 对于
Say:Saying: {message} - 对于
Move:Moving {steps} steps {direction} - 对于
Calculate:{a} + {b} = {sum}
你的输出应将每条命令的结果单独显示在一行中:
Saying: {message}
Moving {steps} steps {direction}
{a} + {b} = {sum}例如,假设 say 消息是 "Hello world",移动方向是 "north"、步数是 5,并且要计算 10 和 25,输出将是:
Saying: Hello world
Moving 5 steps north
10 + 25 = 35你将收到五个输入:say 消息、方向、步数,以及要进行计算的两个数字。
亲手试试
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_message 创建 Say 命令并执行
// TODO:使用 direction 和 steps 创建 Move 命令并执行
// TODO:使用 num1 和 num2 创建 Calculate 命令并执行
// TODO:打印每个命令的执行结果
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器