结构体与枚举
struct、enum、pattern matching、impl blocks。
结构体与枚举
这一课你将能做到
- 用 struct 建模数据(含方法与关联函数),用 enum 建模「多态状态」
- 熟练使用 match 做穷尽式模式匹配,含解构与绑定
- 用 Option 处理「可能没有」的值,掌握 if let 与 let else
为什么要学
Rust 没有 class 和继承,数据建模靠两个原语:struct 管数据形状,enum 管「可能是这几种情况之一」。组合起来能表达 Java 里要靠继承树或 sealed interface 才能表达的东西,而且 match 的穷尽性检查保证新增状态时所有处理点都被编译器揪出来。
判题系统的核心状态机——AC/WA/TLE/RE——就是 enum 的教科书场景。Java 21 的 record + sealed + switch 模式匹配正在向 Rust 靠拢,学完这课你对两种语言的理解都会加深。
先建立图像
// struct:值的形状(Java 的 record/POJO)
struct Submission {
id: u64,
language: String,
}
// enum:可能的状态集合,每个变体可以携带不同的数据(Java enum + sealed interface 合体)
enum Verdict {
Accepted { time_ms: u32 }, // 结构体风格变体
WrongAnswer(u32, String), // 元组风格:样例号 + 差异信息
CompileError(String), // 单值
TimeLimit, // 无数据
}
match 时编译器强制四种变体全部处理,漏一种就编译失败——这是 Java 的 default 分支给不了的安全性。
跟着做
步骤 1:定义结构体、实现方法
cargo new type-demo
cd type-demo
#[derive(Debug, Clone)] // derive 自动实现调试打印与克隆,第 10 课展开
struct Submission {
id: u64,
language: String,
time_used_ms: u32,
memory_kb: u32,
}
impl Submission {
// 关联函数:没有 self,对标 Java 静态工厂方法。惯例命名 new
fn new(id: u64, language: &str) -> Self {
Self { id, language: language.to_string(), time_used_ms: 0, memory_kb: 0 }
}
// &self:只读方法
fn is_fast(&self) -> bool {
self.time_used_ms < 1000
}
// &mut self:可修改自身
fn record(&mut self, time_ms: u32, mem_kb: u32) {
self.time_used_ms = time_ms;
self.memory_kb = mem_kb;
}
}
fn main() {
let mut sub = Submission::new(1, "cpp");
sub.record(128, 4096);
println!("{sub:?}"); // {:?} 走 Debug derive
println!("达标:{}", sub.is_fast());
}
三种 self:self 拿走所有权(少用)、&self 只读借用(默认选择)、&mut self 可变借用。
步骤 2:枚举携带数据
#[derive(Debug, Clone, PartialEq)]
enum Verdict {
Accepted { time_ms: u32 },
WrongAnswer(u32, String),
CompileError(String),
TimeLimit,
}
fn main() {
let results = vec![
Verdict::Accepted { time_ms: 128 },
Verdict::WrongAnswer(3, "expected 42, got 41".into()),
Verdict::CompileError("undefined reference".into()),
Verdict::TimeLimit,
];
for v in &results {
println!("{v:?}");
}
}