Rust模块(modules)

Rust 提供了一套强大的模块(module)系统,可以将代码按层次分成多个逻辑 单元(模块),并管理这些模块之间的可见性(公有(public)或私有(private))。

模块是项(item)的集合,项可以是:函数,结构体,trait,impl 块,甚至其它模块。

可见性

默认情况下,模块中的项拥有私有的可见性(private visibility),不过可以加上 pub 修饰语来重载这一行为。模块中只有公有的(public)项可以从模块外的作用域 访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#[allow(non_snake_case)]
#[allow(dead_code)]
mod first{
//默认私有
fn firstPrivate(){
println!("firstPrivate");
}
//定义公有
pub fn firstPublic(){
println!("firstPublic");
}
//嵌套模块
pub mod second{
//默认私有
fn secondPrivate(){
println!("secondPrivate");
}
//定义公有
pub fn secondPublic(){
println!("secondPublic");
}
//只在当前模块可见
pub(self) fn secondPublicSelf(){
println!("secondPublicSelf");
}
//父模块可见
pub(super) fn secondPublicSuper(){
println!("secondPublicSuper");
}

pub mod third{
//父模块可见
pub(super) fn thirdPublicSuper(){
println!("thirdPublicSuper");
}

// 使用 `pub(in path)` 语法定义的函数只在给定的路径中可见。
// `path` 必须是父模块(parent module)或祖先模块(ancestor module),这里first和second都可以调用
pub(in crate::first) fn thirdFunctionInFirst(){
println!("thirdFunctionInFirst");
}
}
pub fn function(){
secondPublicSelf();
third::thirdFunctionInFirst();
third::thirdPublicSuper();
}

}

pub fn function(){
firstPublic();
firstPrivate();

//包含secondPublicSelf third::thirdFunctionInFirst(); third::thirdPublicSuper();
second::function();

second::secondPublic();
// secondPrivate(); error
second::secondPublicSuper();

}
}

fn main(){
first::function();
}

运行结果如下:

1
2
3
4
5
6
7
firstPublic
firstPrivate
secondPublicSelf
thirdFunctionInFirst
thirdPublicSuper
secondPublic
secondPublicSuper

通过上面的例子可以看出一下几点:

  • 模块是可以嵌套的。
  • 模块中方法默认为私有,只能自己调用。
  • 只声明pub为公有,任何地方都可以调用。
  • 声明pub(self)为当前模块可见。
  • 声明pub(super)为父模块可见(只有父模块)。
  • 声明pub(in path)为指定路径向下可见(包括指定路径)。

结构体可见性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
fn main() {
mod my{
pub struct OpenBox<T>{
pub contents : T
}

pub struct ClosedBox<T>{
contents :T
}

impl<T> ClosedBox<T> {
// 一个公有的构造器方法
pub fn new(contents: T) -> ClosedBox<T> {
ClosedBox {
contents: contents,
}
}
}
}

let open_box = my::OpenBox{contents:"open_box"};
println!("{}",open_box.contents);

// let closed_box = my::ClosedBox{contents:"close_box"}; error

let closed_box = my::ClosedBox::new("close_box");
// println!("{}",closed_box.contents); error
}

use声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fn main(){
use first::second::function as out_function;
fn function(){
println!("{}","function");
}

mod first{
pub mod second{
pub fn function(){
println!("{}","first::second::function()");
}
}
}
out_function();
{
use first::second::function;
function();
}
function();
}

super和self

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
fn function() {
println!("called `function()`");
}

mod cool {
pub fn function() {
println!("called `cool::function()`");
}
}

mod my {
fn function() {
println!("called `my::function()`");
}

mod cool {
pub fn function() {
println!("called `my::cool::function()`");
}
}

pub fn indirect_call() {
// 让我们从这个作用域中访问所有名为 `function` 的函数!
print!("called `my::indirect_call()`, that\n> ");

// `self` 关键字表示当前的模块作用域——在这个例子是 `my`。
// 调用 `self::function()` 和直接调用 `function()` 都得到相同的结果,
// 因为他们表示相同的函数。
self::function();
function();

// 我们也可以使用 `self` 来访问 `my` 内部的另一个模块:
self::cool::function();
cool::function();

// `super` 关键字表示父作用域(在 `my` 模块外面)。
super::function();

// 这将在 *crate* 作用域内绑定 `cool::function` 。
// 在这个例子中,crate 作用域是最外面的作用域。
{
use crate::cool::function as root_function;
root_function();
}
}
}

fn main() {
my::indirect_call();
}

打印结果:

1
2
3
4
5
6
7
called `my::indirect_call()`, that
> called `my::function()`
called `my::function()`
called `my::cool::function()`
called `my::cool::function()`
called `function()`
called `cool::function()`

模块文件分层

模块可以分配到文件/目录的层次结构中。

1
2
3
4
5
6
7
$ tree .
.
|-- my
| |-- inaccessible.rs
| |-- mod.rs
| `-- nested.rs
`-- main.rs

main.rs 的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 此声明将会查找名为 `my.rs` 或 `my/mod.rs` 的文件,并将该文件的内容放到
// 此作用域中一个名为 `my` 的模块里面。
mod my;

fn function() {
println!("called `function()`");
}

fn main() {
my::function();

function();

my::indirect_access();

my::nested::function();
}

my/mod.rs 的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 类似地,`mod inaccessible` 和 `mod nested` 将找到 `nested.rs` 和
// `inaccessible.rs` 文件,并在它们放到各自的模块中。
mod inaccessible;
pub mod nested;

pub fn function() {
println!("called `my::function()`");
}

fn private_function() {
println!("called `my::private_function()`");
}

pub fn indirect_access() {
println!("called `my::indirect_access()`");

private_function();
}

my/nested.rs 的内容:

1
2
3
4
5
6
7
8
pub fn function() {
println!("called `my::nested::function()`");
}

#[allow(dead_code)]
fn private_function() {
println!("called `my::nested::private_function()`");
}

my/inaccessible.rs 的内容:

1
2
3
4
#[allow(dead_code)]
pub fn public_function() {
println!("called `my::inaccessible::public_function()`");
}

执行打印结果:

1
2
3
4
5
6
called `my::function()`
called `function()`
called `my::indirect_access()`
called `my::private_function()`
called `my::inaccessible::public_function()`
called `my::nested::function()`