《Rust编程入门》11.3 公有性与私有性

11.3 公有性与私有性 在 Rust 中,模块系统提供了强大的访问控制功能,通过定义项目中项(如模块、函数、结构体、字段和枚举)是 公有(public) 还是 私有(private),开发者可以清晰地表达哪些部分是对外可见的公共接口,哪些是内部实现的细节。

11.3 公有性与私有性

在 Rust 中,模块系统提供了强大的访问控制功能,通过定义项目中项(如模块、函数、结构体、字段和枚举)是 公有(public) 还是 私有(private),开发者可以清晰地表达哪些部分是对外可见的公共接口,哪些是内部实现的细节。


11.3.1 私有性(默认行为)

在 Rust 中,所有的模块、函数、结构体、枚举、字段等项,默认是私有的,仅在当前模块及其子模块中可见。

示例:默认私有性

mod greetings {
    fn say_hello() {
        println!("Hello, private world!");
    }

    pub fn public_hello() {
        say_hello(); // 私有函数在模块内可以被调用
        println!("Hello, public world!");
    }
}

fn main() {
    greetings::public_hello(); // 可以调用公共函数
    // greetings::say_hello(); // 错误:私有函数无法访问
}

在上例中:

  • say_hello 函数默认是私有的,仅 greetings 模块内可见。
  • public_hello 是公共的(通过 pub 标记),可以在模块外被访问。

11.3.2 公有性(pub 关键字)

通过 pub 关键字,可以将模块中的项标记为公共的,对外部模块可见。

示例:公共函数

mod library {
    pub fn find_book() {
        println!("Finding a book...");
    }
}

fn main() {
    library::find_book(); // 调用公共函数
}

公共模块

模块本身也可以是公共的,通过 pub mod 定义:

pub mod library {
    pub fn find_book() {
        println!("Finding a book...");
    }
}

在外部模块中导入公共模块:

mod library;

fn main() {
    library::find_book(); // 调用公共模块中的函数
}

11.3.3 结构体与枚举的公有性

结构体的公有性

结构体本身可以通过 pub 标记为公共,但其字段默认是私有的。如果需要字段可被外部访问,必须单独为字段添加 pub

pub struct Book {
    pub title: String,  // 公共字段
    author: String,     // 私有字段
}

impl Book {
    pub fn new(title: &str, author: &str) -> Self {
        Self {
            title: title.to_string(),
            author: author.to_string(),
        }
    }

    pub fn get_author(&self) -> &str {
        &self.author
    }
}

fn main() {
    let book = Book::new("Rust Programming", "John Doe");
    println!("Title: {}", book.title); // 可访问公共字段
    // println!("Author: {}", book.author); // 错误:私有字段无法访问
    println!("Author: {}", book.get_author()); // 通过公共方法访问私有字段
}

枚举的公有性

枚举类型如果是公共的,其所有变体默认也是公共的:

pub enum Color {
    Red,
    Green,
    Blue,
}

fn main() {
    let color = Color::Red; // 枚举变体可以被直接访问
}

11.3.4 公共接口的设计

Rust 的私有性规则提供了封装的能力。通过合理设计公有接口,可以隐藏实现细节,仅暴露必要的功能:

示例:封装实现细节

mod library {
    struct Book {
        title: String,
        author: String,
    }

    pub fn create_book(title: &str, author: &str) -> Book {
        Book {
            title: title.to_string(),
            author: author.to_string(),
        }
    }

    pub fn print_book_info(book: &Book) {
        println!("Title: {}, Author: {}", book.title, book.author);
    }
}

fn main() {
    let book = library::create_book("Rust in Action", "Tim McNamara");
    library::print_book_info(&book); // 可以通过公共函数访问私有字段
}

在此示例中:

  • Book 结构体是私有的,无法直接在模块外访问。
  • 提供公共函数 create_bookprint_book_info,作为对外暴露的接口。

11.3.5 pub(crate)pub(super)

Rust 支持更精细化的可见性控制,通过 pub(crate)pub(super) 控制项的访问范围。

pub(crate)

pub(crate) 表示该项在当前 crate 内部是公共的,但对 crate 外部不可见。

mod library {
    pub(crate) fn internal_fn() {
        println!("This is a crate-public function.");
    }
}

fn main() {
    library::internal_fn(); // 当前 crate 内可以访问
}

pub(super)

pub(super) 表示该项在父模块中是公共的,但对子模块或更外层模块不可见。

mod parent {
    pub mod child {
        pub(super) fn visible_to_parent() {
            println!("This is visible to the parent module.");
        }
    }

    pub fn use_child_fn() {
        child::visible_to_parent(); // 父模块可以访问
    }
}

fn main() {
    parent::use_child_fn(); // 通过父模块调用子模块的函数
}

11.3.6 私有性与模块设计建议

  1. 隐藏实现细节:尽量将内部逻辑标记为私有,仅暴露需要的接口。
  2. 明确公共接口:使用 pub 定义清晰的模块 API,避免不必要的项暴露。
  3. 合理使用层级可见性:通过 pub(crate)pub(super) 控制访问范围,保护内部逻辑。
  4. 设计易于维护的模块结构:确保模块之间的依赖关系清晰,避免交叉依赖。

11.3.7 小结

Rust 的公有性与私有性机制是模块系统的重要组成部分:

  • 默认私有性保障了模块间的隔离。
  • 通过 pub 关键字灵活定义公共接口。
  • pub(crate)pub(super) 提供了更精细化的可见性控制。
  • 合理利用访问控制可以设计清晰、可维护的代码。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页