Rust中的Enum与Struct详解

在 Rust 中,struct(结构体)和enum(枚举)是两种核心的自定义类型,分别用于组合相关数据表示互斥的可能性

结构体struct

struct用于将多个相关的值组合在一起,形成一个有意义的组

具名结构体(named strcut)

最常用的结构体形式,字段有明确的名称,可读性强,适合数据含义明确的场景。

  • 字段默认私有(仅当前模块内可见)
  • 通过impl实现关联函数(方法)
  • 通过..实现赋值(所有未指定的字段,全部替换为...对应变量中的):若字段为移动语义,所有权被移走
  • 通过trait实现多态(参见《Rust中的特征Trait》)
rust 复制代码
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 TraitBox<dyn Trait>)通过虚函数表(vtable),在运行时分发(适合异构集合/插件式架构)。
rust 复制代码
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》),也可以带生命周期参数。

rust 复制代码
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)

字段没有名称,仅通过位置区分,适合数据结构简单、字段含义可通过位置推断的场景。

rust 复制代码
// 元组结构体:通过位置区分(x, y)
struct Point(i32, i32);  

// 创建实例
let p1 = Point(3, 4);
// 访问字段(通过索引)
println!("x坐标:{}", p1.0);  // 输出:x坐标:3

单元结构体(unit struct)

一种不包含任何字段的结构体。它的定义形式类似于一个"空"的结构体:

  • 在内存中不占用任何空间(size_of::<UnitStruct>() == 0
  • 主要用于标记类型(表示 "存在性" 而非 "数据")
rust 复制代码
// 定义状态
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关键字定义,每个变体可以是 "空" 的,也可以携带数据(类似元组或结构体)。

rust 复制代码
// 定义枚举:消息类型
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表达式匹配其变体,从而处理不同情况(类似 "多分支条件判断",但更安全)。

rust 复制代码
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)问题。

rust 复制代码
enum Option<T> {
    Some(T),  // 有值:存储类型为T的值
    None,     // 无值
}

Result<T, E>用于表示操作 "成功" 或 "失败" 的结果,是 Rust 错误处理的核心类型。

rust 复制代码
enum Result<T, E> {
    Ok(T),   // 成功:存储类型为T的结果
    Err(E),  // 失败:存储类型为E的错误信息
}

Ordering用于表示两个值的比较结果(小于、等于、大于)

rust 复制代码
enum Ordering {
    Less,    // 小于
    Equal,   // 等于
    Greater, // 大于
}
相关推荐
DongLi014 天前
rustlings 学习笔记 -- exercises/05_vecs
rust
番茄灭世神4 天前
Rust学习笔记第2篇
rust·编程语言
shimly1234564 天前
(done) 速通 rustlings(20) 错误处理1 --- 不涉及Traits
rust
shimly1234564 天前
(done) 速通 rustlings(19) Option
rust
@atweiwei4 天前
rust所有权机制详解
开发语言·数据结构·后端·rust·内存·所有权
shimly1234564 天前
(done) 速通 rustlings(24) 错误处理2 --- 涉及Traits
rust
shimly1234565 天前
(done) 速通 rustlings(23) 特性 Traits
rust
shimly1234565 天前
(done) 速通 rustlings(17) 哈希表
rust
shimly1234565 天前
(done) 速通 rustlings(15) 字符串
rust
shimly1234565 天前
(done) 速通 rustlings(22) 泛型
rust