Menu
CoddyTech

匹配数据变体

本课属于 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)。

你选择的变量名会在对应的匹配分支中可用。这很实用,因为你可以同时检查自己拥有哪种变体,并且访问它携带的数据。

编译器会确保你处理每个变体,提取出的值可以立即使用,无需额外步骤。

challenge icon

挑战

简单

我们来构建一个命令处理器,用来处理不同类型的用户命令。每个命令携带不同的数据,你的处理器会使用模式匹配提取这些数据,并生成相应的响应。

你将创建两个文件来组织代码:

  • 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:打印每个命令的执行结果
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Rust 在线编译器