枚举上的方法
本课属于 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)
}
这种模式很强大,因为调用者不需要知道自己使用的是哪个变体。只需调用方法,枚举就会在内部处理其余部分。行为会根据变体而变化,但接口保持一致。
挑战
简单让我们构建一个交通灯系统,使用带方法的枚举来描述当前信号状态。每种灯色都会携带其持续时间信息,并由一个方法提供易于理解的描述。
你将创建两个文件来组织代码:
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 方法并打印结果
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器