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 TraitBox<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, // 大于
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值