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, // 大于
}
相关推荐
盒马盒马3 小时前
Rust:Windows 系统 VsCode 环境搭建
windows·vscode·rust
摘星编程3 小时前
深入浅出 Tokio 源码:掌握 Rust 异步编程的底层逻辑
网络·算法·rust·系统编程·tokio
于顾而言3 小时前
【笔记】Comprehensive Rust语言学习
笔记·学习·rust
alwaysrun1 天前
Rust中的智能指针
rust·智能指针·pin·cow·box·arc
fqbqrr2 天前
2510rs,rust,1.88
rust
fqbqrr2 天前
2510rs,rust,1.90
rust
Brianna Home2 天前
Rust内存安全:所有权与生命周期的精妙设计
大数据·rust
ZJU_统一阿萨姆2 天前
Windows系统VSCode配置Rust开发环境(超详细保姆级教程)
windows·vscode·rust
zzywxc7872 天前
解锁 Rust 开发新可能:从系统内核到 Web 前端的全栈革命
开发语言·前端·python·单片机·嵌入式硬件·rust·scikit-learn