11.3 公有性与私有性
在 Rust 中,模块系统提供了强大的访问控制功能,通过定义项目中项(如模块、函数、结构体、字段和枚举)是 公有(public) 还是 私有(private),开发者可以清晰地表达哪些部分是对外可见的公共接口,哪些是内部实现的细节。
11.3.1 私有性(默认行为)
在 Rust 中,所有的模块、函数、结构体、枚举、字段等项,默认是私有的,仅在当前模块及其子模块中可见。
示例:默认私有性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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
关键字,可以将模块中的项标记为公共的,对外部模块可见。
示例:公共函数
1
2
3
4
5
6
7
8
9
|
mod library {
pub fn find_book() {
println!("Finding a book...");
}
}
fn main() {
library::find_book(); // 调用公共函数
}
|
公共模块
模块本身也可以是公共的,通过 pub mod
定义:
1
2
3
4
5
|
pub mod library {
pub fn find_book() {
println!("Finding a book...");
}
}
|
在外部模块中导入公共模块:
1
2
3
4
5
|
mod library;
fn main() {
library::find_book(); // 调用公共模块中的函数
}
|
11.3.3 结构体与枚举的公有性
结构体的公有性
结构体本身可以通过 pub
标记为公共,但其字段默认是私有的。如果需要字段可被外部访问,必须单独为字段添加 pub
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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()); // 通过公共方法访问私有字段
}
|
枚举的公有性
枚举类型如果是公共的,其所有变体默认也是公共的:
1
2
3
4
5
6
7
8
9
|
pub enum Color {
Red,
Green,
Blue,
}
fn main() {
let color = Color::Red; // 枚举变体可以被直接访问
}
|
11.3.4 公共接口的设计
Rust 的私有性规则提供了封装的能力。通过合理设计公有接口,可以隐藏实现细节,仅暴露必要的功能:
示例:封装实现细节
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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_book
和 print_book_info
,作为对外暴露的接口。
11.3.5 pub(crate)
和 pub(super)
Rust 支持更精细化的可见性控制,通过 pub(crate)
和 pub(super)
控制项的访问范围。
pub(crate)
pub(crate)
表示该项在当前 crate 内部是公共的,但对 crate 外部不可见。
1
2
3
4
5
6
7
8
9
|
mod library {
pub(crate) fn internal_fn() {
println!("This is a crate-public function.");
}
}
fn main() {
library::internal_fn(); // 当前 crate 内可以访问
}
|
pub(super)
pub(super)
表示该项在父模块中是公共的,但对子模块或更外层模块不可见。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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 私有性与模块设计建议
- 隐藏实现细节:尽量将内部逻辑标记为私有,仅暴露需要的接口。
- 明确公共接口:使用
pub
定义清晰的模块 API,避免不必要的项暴露。
- 合理使用层级可见性:通过
pub(crate)
和 pub(super)
控制访问范围,保护内部逻辑。
- 设计易于维护的模块结构:确保模块之间的依赖关系清晰,避免交叉依赖。
11.3.7 小结
Rust 的公有性与私有性机制是模块系统的重要组成部分:
- 默认私有性保障了模块间的隔离。
- 通过
pub
关键字灵活定义公共接口。
pub(crate)
和 pub(super)
提供了更精细化的可见性控制。
- 合理利用访问控制可以设计清晰、可维护的代码。