带数据的枚举
本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 14 课,共 61 课。
Rust 中的基本枚举可以让你定义一个具有固定变体集合的类型,例如 Direction::North 或 Status::Active。不过,Rust 枚举的功能远不止于此。每个变体都可以携带自己的数据,这让枚举在模拟现实场景时非常灵活。
考虑一个消息系统,其中不同类型的消息携带不同的信息。文本消息有内容,移动命令有坐标,而退出信号什么也不包含。在 Rust 中,你可以用一个 enum 表示所有这些:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
每个变体都有不同的形状。Quit 不包含任何数据:它只是一个信号。
Move 使用类似结构体的语法,并带有命名字段。Write 使用元组语法,包含一个 String。ChangeColor 包含三个表示 RGB 分量的值。
创建这些变体的实例如下:
let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("Hello"));
let m4 = Message::ChangeColor(255, 128, 0);
这种方法的妙处在于,m1、m2、m3 和 m4 的类型都相同:Message。你可以把它们存储在同一个集合中,传递给同一个函数,或者从一个函数中返回任意一种变体。枚举将不同的数据形状统一为一种类型,同时保留每种变体所需的具体信息。
挑战
简单让我们构建一个通知系统,使用带数据的枚举来表示不同类型的提醒。每种通知类型都携带不同的信息:有些包含消息,有些包含数字值,还有些只是简单的信号。
你将创建两个文件来整理代码:
notification.rs:定义一个公开的Notification枚举,其中包含三个变体:Alert:包含一条String消息(元组语法)Reminder:包含命名字段:title(String)和minutes(u32)Dismiss:不包含数据,只是一个信号
main.rs:引入通知模块,并为每个变体创建一个实例。然后打印每条通知的信息,以展示这三个变体属于同一种类型,但携带不同的数据。
打印时,使用调试格式({:?})来显示每条通知。你需要为枚举派生 Debug 特征,才能用这种方式打印。
输出应显示全部三条通知,每条占一行:
Alert("{message}")
Reminder { title: "{title}", minutes: {minutes} }
Dismiss例如,提醒消息为 "Server down",提醒标题为 "Meeting",分钟数为 30 时,输出如下:
Alert("Server down")
Reminder { title: "Meeting", minutes: 30 }
Dismiss你将收到三个输入:提醒消息、提醒标题和提醒分钟数。
亲手试试
mod notification;
use notification::Notification;
fn main() {
// 读取输入
let mut alert_message = String::new();
std::io::stdin().read_line(&mut alert_message).expect("Failed to read line");
let alert_message = alert_message.trim().to_string();
let mut reminder_title = String::new();
std::io::stdin().read_line(&mut reminder_title).expect("Failed to read line");
let reminder_title = reminder_title.trim().to_string();
let mut minutes_input = String::new();
std::io::stdin().read_line(&mut minutes_input).expect("Failed to read line");
let reminder_minutes: u32 = minutes_input.trim().parse().expect("Failed to parse minutes");
// TODO:使用 alert_message 创建 Alert 通知
// TODO:使用 reminder_title 和 reminder_minutes 创建 Reminder 通知
// TODO:创建 Dismiss 通知
// TODO:使用调试格式 {:?} 打印每条通知
// 每条通知单独打印一行
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器