学习笔记十八——Rust 封装

发布于:2025-04-20 ⋅ 阅读:(9) ⋅ 点赞:(0)

🧱 Rust 封装终极指南:结构体、模块、Trait、目录结构与模块引用


🧭 目录导航

  1. 什么是封装?Rust 的封装理念
  2. Rust 的封装工具总览
  3. 模块(mod)和访问控制(pub)详解
  4. 结构体和枚举:封装数据
  5. implself:封装行为
  6. Trait:行为的抽象封装与多态实现
  7. 目录结构设计与模块引用
  8. 实战案例:带 Trait 的完整封装模块系统
  9. 总结:Rust 的封装哲学

1️⃣ 什么是封装?Rust 是怎么理解封装的?

封装的本质是:

将数据与操作它的方法组织在一起,并对外隐藏实现细节,只暴露对外接口。

Rust 提供了现代化、静态安全的封装机制,它不像 Java 有 class,但功能上实现了同样甚至更强的封装能力。


2️⃣ Rust 的封装工具总览

工具 功能 举例
struct / enum 封装一组字段 struct User { name, password }
impl 给数据添加方法 impl User { fn login(&self) { ... } }
mod + pub 封装逻辑模块 + 控制访问 mod user;, pub fn login()
trait 抽象行为、实现接口、多态封装 trait Printable { fn print(&self); }

3️⃣ 模块和 pub:控制访问边界

Rust 的模块系统是封装最重要的边界控制工具。

  • 所有内容默认私有
  • pub 显式开放
  • 模块和目录一一对应(mod.rs 或新写法 modname.rs + 子模块)

4️⃣ 结构体和枚举:封装数据

pub struct User {
    pub name: String,
    password: String, // 私有字段
}

pub enum LoginStatus {
    Success,
    Failure(String),
}
  • struct 封装实体数据
  • enum 封装状态、结果、多种可能性

5️⃣ impl 和 self:封装方法与行为

impl User {
    pub fn new(name: &str, pwd: &str) -> Self {
        Self {
            name: name.to_string(),
            password: pwd.to_string(),
        }
    }

    pub fn check_password(&self, input: &str) -> bool {
        self.password == input
    }
}

6️⃣ Trait:封装行为的抽象方式

✅ 什么是 Trait?

Trait(特征)类似于 Java 的接口(interface):

  • 它定义了某种能力/行为的抽象
  • structenum 可以实现多个 trait
  • 外部通过 trait 使用对象,无需关心具体类型

🧠 举个例子:定义一个能“打印”的 trait

pub trait Printable {
    fn print(&self);
}

实现 trait:

pub struct User {
    pub name: String,
}

impl Printable for User {
    fn print(&self) {
        println!("User: {}", self.name);
    }
}

🛠 Trait 的用法和封装意义

  1. 隐藏内部结构,只暴露行为接口
  2. 支持多态:多个类型实现同一个 trait
  3. 实现解耦:代码依赖于 trait 而不是具体类型

✨ Trait 封装进模块

你可以将 trait 和实现都封装在模块里:

// user/traits.rs
pub trait Printable {
    fn print(&self);
}
// user/mod.rs
mod traits;
pub use traits::Printable;

pub struct User {
    pub name: String,
}

impl Printable for User {
    fn print(&self) {
        println!("User: {}", self.name);
    }
}

外部模块这样使用:

use user::{User, Printable};

fn main() {
    let u = User { name: "Tom".to_string() };
    u.print(); // 调用 trait 方法
}

🧪 高级技巧:Trait 作为函数参数(多态)

fn show_info(item: &impl Printable) {
    item.print();
}

或更通用写法:

fn show_info<T: Printable>(item: &T) {
    item.print();
}

这样你就实现了“只看能力,不看具体类型”。


7️⃣ 模块系统与封装结构设计

项目结构举例(目录 + 封装 + trait):

src/
├── main.rs
├── user/
│   ├── mod.rs
│   ├── model.rs      // 数据结构
│   ├── service.rs    // 行为逻辑
│   └── traits.rs     // trait 定义
├── order/
│   ├── mod.rs
│   └── db.rs
└── utils.rs

每个模块目录都包含一个 mod.rs,作为该模块的根,里面:

pub mod model;
pub mod service;
pub mod traits;

pub use traits::*;
pub use model::User;

然后在 main.rs 中:

mod user;

use user::{User, Printable};

fn main() {
    let user = User::new("Alice");
    user.print();
}

🧠 8️⃣ 封装案例总结:Trait + 模块 + impl 的组合拳

内容 用途 封装表现
struct / enum 数据载体 私有字段保护数据不被外部访问
impl 方法实现 把行为挂在数据上
trait 抽象接口 通过能力驱动调用,不关心类型
mod / pub 模块组织 文件结构决定模块结构,pub 决定可访问性
目录结构 工程可维护性 按功能拆模块,模块拆 trait/model/service

✅ 9️⃣ 最终总结:Rust 封装哲学一句话

“能看什么是你说了算,能做什么是 trait 决定的,内部怎么做是我的事。”

Rust 提供了非常强大且显式的封装能力,它将“数据安全、接口清晰、逻辑隔离”做到了极致。


网站公告

今日签到

点亮在社区的每一天
去签到