Menu
CoddyTech

枚举上的方法

本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 15 课,共 61 课。

和结构体一样,你可以在 impl 块中为枚举定义方法。这样,你就能将行为直接关联到枚举类型,方便通过统一的接口处理不同的变体。

以下是如何为上一课中的 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 来判断当前处理的是哪个变体,并返回相应的结果。

无论你使用哪种变体,调用方法的方式都相同:

fn main() {
    let m1 = Message::Quit;
    let m2 = Message::Move { x: 10, y: 20 };
    
    println!("{}", m1.describe());  // 退出信号
    println!("{}", m2.describe());  // 移动到 (10, 20)
}

这种模式很强大,因为调用者不需要知道自己使用的是哪个变体。只需调用方法,枚举就会在内部处理其余部分。行为会根据变体而变化,但接口保持一致。

challenge icon

挑战

简单

让我们构建一个交通灯系统,使用带方法的枚举来描述当前信号状态。每种灯色都会携带其持续时间信息,并由一个方法提供易于理解的描述。

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

  • traffic.rs:定义一个包含三个变体的公有 TrafficLight 枚举:
    • Red:包含一个 u32,表示需要等待的秒数
    • Yellow:包含一个 u32,表示需要等待的秒数
    • Green:包含一个 u32,表示可以通行的秒数
    然后实现一个 status 方法,返回描述灯色的 String。在方法中使用 match 处理每个变体,并在消息中包含持续时间。
  • main.rs:引入你的交通灯模块,创建每种灯色变体的实例,并对每个实例调用 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 在线编译器