Rust中的Enum与Struct详解
在 Rust 中,struct(结构体)和enum(枚举)是两种核心的自定义类型,分别用于组合相关数据和表示互斥的可能性。
结构体struct
struct用于将多个相关的值组合在一起,形成一个有意义的组
具名结构体(named strcut)
最常用的结构体形式,字段有明确的名称,可读性强,适合数据含义明确的场景。
- 字段默认私有(仅当前模块内可见)
- 通过impl实现关联函数(方法)
- 通过
..实现赋值(所有未指定的字段,全部替换为…对应变量中的):若字段为移动语义,所有权被移走 - 通过trait实现多态(参见《Rust中的特征Trait》)
use std::fmt;pub struct Person {pub name: String,age: u8,active: bool,
}impl fmt::Display for Person {fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {write!(f, "Person {{ name: {}, age: {}, active: {} }}", self.name, self.age, self.active)}
}fn main() {let alice = Person { name: String::from("Alice"), age: 30, active: true };let mike = Person { name: String::from("Mike"), ..alice };println!("person: {}", mike);// 解结构与..let Person { name, .. } = mike;println!("name: {}", name);
}
可见性
默认为私有,可通过pub修饰符修改:
| 修饰符 | 可见范围 | 说明 |
|---|---|---|
pub | 全局可见(跨 crate) | 完全公开 |
pub(crate) | 整个当前 crate 内可见 | 库内部共享 |
pub(super) | 父模块可见 | 子模块辅助函数 |
pub(in path) | 指定模块路径内可见 | 最灵活的控制 |
| (无修饰) | 当前模块私有 | 默认私有 |
trait(继承/多态)
Rust 没有传统 OOP 的类继承(没有基类/子类)。用 trait + impl 来实现接口/多态。
trait定义方法签名集合,实现trait的类必须提供所有对应方法:
- 静态分发(
T: Trait)在编译期确定具体类型(单态化,性能好)。 - 动态分发(
&dyn Trait或Box<dyn Trait>)通过虚函数表(vtable),在运行时分发(适合异构集合/插件式架构)。
trait Drawable {fn draw(&self);
}struct Circle { radius: f64 }
struct Square { side: f64 }impl Drawable for Circle {fn draw(&self) { println!("circle r={}", self.radius); }
}
impl Drawable for Square {fn draw(&self) { println!("square s={}", self.side); }
}// 静态分发(泛型)
fn draw_all<T: Drawable>(items: &[T]) {for item in items { item.draw(); }
}// 动态分发(trait object)
fn draw_box(items: &[Box<dyn Drawable>]) {for item in items { item.draw(); }
}
泛型与生命周期
结构体可以是泛型的(参见《Rust中的泛型Generics》),也可以带生命周期参数。
struct Holder<'a, T> { r: &'a T, val: T }
struct Pair<T, U>(T, U);
泛型说明:
| 特性 | 说明 |
|---|---|
struct Point<T> | 定义泛型结构体 |
impl<T> Point<T> | 为所有类型实现方法 |
impl Point<i32> | 为特定类型实现方法 |
T: Display | 泛型约束,要求类型实现Displaytrait |
where T: Clone, U: Debug | 泛型约束,更清晰的约束语法 |
元组结构体(tuple struct)
字段没有名称,仅通过位置区分,适合数据结构简单、字段含义可通过位置推断的场景。
// 元组结构体:通过位置区分(x, y)
struct Point(i32, i32); // 创建实例
let p1 = Point(3, 4);
// 访问字段(通过索引)
println!("x坐标:{}", p1.0); // 输出:x坐标:3
单元结构体(unit struct)
一种不包含任何字段的结构体。它的定义形式类似于一个“空”的结构体:
- 在内存中不占用任何空间(
size_of::<UnitStruct>() == 0) - 主要用于标记类型(表示 “存在性” 而非 “数据”)
// 定义状态
pub struct Locked;
pub struct Unlocked;// 门的结构,使用泛型参数表示状态
pub struct Door<TState> {id: u32,_state: std::marker::PhantomData<TState>,
}// 只有 Locked 状态才能解锁
impl Door<Locked> {fn unlock(self) -> Door<Unlocked> {println!("门 {} 已解锁", self.id);Door {id: self.id,_state: std::marker::PhantomData,}}
}// 只有 Unlocked 状态才能打开
impl Door<Unlocked> {fn open(&self) {println!("门 {} 打开", self.id);}fn lock(self) -> Door<Locked> {println!("门 {} 已上锁", self.id);Door {id: self.id,_state: std::marker::PhantomData,}}
}pub fn test_door() {let door = Door::<Locked> {id: 101,_state: std::marker::PhantomData,}; let door = door.unlock(); // 状态转换door.open(); // Unlocked 状态可以打开let door = door.lock(); // 重新上锁
}
枚举(enum)
枚举的核心作用是定义一个类型,其值是有限的、互斥的几种可能变体(variants)之一。每个变体可以关联不同类型和数量的数据。
枚举通过enum关键字定义,每个变体可以是 “空” 的,也可以携带数据(类似元组或结构体)。
// 定义枚举:消息类型
enum Message {Quit, // 无数据:退出消息Move { x: i32, y: i32 }, // 具名数据:移动到(x,y)Write(String), // 元组数据:写入文本ChangeColor(i32, i32, i32), // 元组数据:修改颜色(RGB)
}// 创建枚举实例
let msg1 = Message::Quit; // 退出消息
let msg2 = Message::Move { x: 10, y: 20 }; // 移动到(10,20)
let msg3 = Message::Write(String::from("hello")); // 写入"hello"
模式匹配
枚举的核心用法是通过match表达式匹配其变体,从而处理不同情况(类似 “多分支条件判断”,但更安全)。
fn process_message(msg: Message) {match msg {Message::Quit => println!("收到退出消息"),Message::Move { x, y } => println!("移动到坐标:({}, {})", x, y),Message::Write(text) => println!("写入内容:{}", text),Message::ChangeColor(r, g, b) => println!("修改颜色为 RGB({}, {}, {})", r, g, b),}
}process_message(msg2); // 输出:移动到坐标:(10, 20)
process_message(msg3); // 输出:写入内容:hello
常见enum
Option<T>是 Rust 中用于表示 “有值” 或 “无值” 的枚举,彻底避免了空指针(Null)问题。
enum Option<T> {Some(T), // 有值:存储类型为T的值None, // 无值
}
Result<T, E>用于表示操作 “成功” 或 “失败” 的结果,是 Rust 错误处理的核心类型。
enum Result<T, E> {Ok(T), // 成功:存储类型为T的结果Err(E), // 失败:存储类型为E的错误信息
}
Ordering用于表示两个值的比较结果(小于、等于、大于)
enum Ordering {Less, // 小于Equal, // 等于Greater, // 大于
}
