@ -38,7 +38,7 @@ mod front_of_house {
## 模块树
在[上一节](https://course.rs/basic/crate-module/crate.html)中,我们提到过 `src/main.rs` 和 `src/lib.rs` 被称为包根(crate root),这个奇葩名称的来源(我不想承认是自己翻译水平太烂-,-) 是由于这两个文件的内容形成了一个模块 `crate` ,该模块位于包的树形结构(由模块组成的树形结构)的根部:
在[上一节](https://course.rs/basic/crate-module/crate.html)中,我们提到过 `src/main.rs` 和 `src/lib.rs` 被称为默认包入口( crate root) , 这个~~奇葩~~名称的来源~~(我不想承认是自己翻译水平太烂-,-)~~ 是由于这两个文件的内容形成了一个模块 `crate` ,该模块位于包的树形结构(由模块组成的树形结构)的根部:
```console
crate
@ -52,7 +52,7 @@ crate
└── take_payment
```
这颗树展示了模块之间**彼此的嵌套**关系,因此被称为**模块树**。其中 `crate` 包根是 `src/lib.rs` 文件,包根 文件中的三个模块分别形成了模块树的剩余部分。
这颗树展示了模块之间**彼此的嵌套**关系,因此被称为**模块树**。其中 `crate` 是 `src/lib.rs` 中定义的包,`src/lib.rs` 文件中的三个模块分别形成了模块树的剩余部分。
#### 父子模块
@ -64,7 +64,7 @@ crate
想要调用一个函数,就需要知道它的路径,在 Rust 中,这种路径有两种形式:
- ** 绝对路径**,从包根开始,路径名以包名或者 `crate` 作为开头
- ** 绝对路径**,从顶层包开始,路径名以顶层包名(本例中为 `crate` ) 作为开头
- ** 相对路径**,从当前模块开始,以 `self` , `super` 或当前模块的标识符作为开头
让我们继续经营那个惨淡的小餐馆,这次为它实现一个小功能:
@ -86,7 +86,7 @@ pub fn eat_at_restaurant() {
}
```
上面的代码为了简化实现,省去了其余模块和函数,这样可以把关注点放在函数调用上。`eat_at_restaurant` 是一个定义在包根 中的函数,在该函数中使用了两种方式对 `add_to_waitlist` 进行调用。
上面的代码为了简化实现,省去了其余模块和函数,这样可以把关注点放在函数调用上。`eat_at_restaurant` 是一个定义在顶层包 `crate` 中的函数,在该函数中使用了两种方式对 `add_to_waitlist` 进行调用。
#### 绝对路径引用
@ -115,7 +115,7 @@ crate
#### 相对路径引用
再回到模块树中,因为 `eat_at_restaurant` 和 `front_of_house` 都处于包根 `crate` 中,因此相对路径可以使用 `front_of_house` 作为开头:
再回到模块树中,因为 `eat_at_restaurant` 和 `front_of_house` 都处于顶层 包 `crate` 中,因此相对路径可以使用 `front_of_house` 作为开头:
```rust
front_of_house::hosting::add_to_waitlist();
@ -156,7 +156,7 @@ crate
## 代码可见性
让我们运行下面(之前) 的代码:
让我们运行下面(之前) 的代码:
```rust
mod front_of_house {
@ -184,7 +184,7 @@ error[E0603]: module `hosting` is private
| ^^^^^^^ private module
```
错误信息很清晰:`hosting` 模块是私有的,无法在包根 进行访问,那么为何 `front_of_house` 模块就可以访问?因为它和 `eat_at_restaurant` 同属于一个包根作用域内,同一个模块内的代码自然不存在私有化问题(所以我们之前章节的代码都没有报过这个错误!) 。
错误信息很清晰:`hosting` 模块是私有的,无法在顶层包 `crate` 中 进行访问,那么为何 `front_of_house` 模块就可以访问?因为它和 `eat_at_restaurant` 同属于一个顶层包的作用域内,同一个模块内的代码自然不存在私有化问题(所以我们之前章节的代码都没有报过这个错误!) 。
模块不仅仅对于组织代码很有用,它还能定义代码的私有化边界:在这个边界内,什么内容能让外界看到,什么内容不能,都有很明确的定义。因此,如果希望让函数或者结构体等类型变成私有化的,可以使用模块。
@ -239,7 +239,8 @@ Bang, 顺利通过编译, 感觉自己又变强了。
在[用路径引用模块](#用路径引用模块)中,我们提到了相对路径有三种方式开始:`self`、`super`和 `crate` 或者模块名,其中第三种在前面已经讲到过,现在来看看通过 `super` 的方式引用模块项。
`super` 代表的是父模块为开始的引用方式,非常类似于文件系统中的 `..` 语法:`../a/b`
< span class = "filename" > 文件名: src/lib.rs< / span >
< span class = "filename" > 文件名:`src/lib.rs`< / span >
```rust
fn serve_order() {}
@ -255,9 +256,9 @@ mod back_of_house {
}
```
嗯,我们的小餐馆又完善了,终于有厨房了!看来第一个客人也快可以有了。。。在厨房模块中,使用 `super::serve_order` 语法,调用了父模块(包根) 中的 `serve_order` 函数。
嗯,我们的小餐馆又完善了,终于有厨房了!看来第一个客人也快可以有了。。。在厨房模块中,使用 `super::serve_order` 语法,调用了父模块 `crate` 中的 `serve_order` 函数。
那么你可能会问,为何不使用 `crate::serve_order` 的方式?额,其实也可以,不过如果你确定未来这种层级关系不会改变,那么 `super::serve_order` 的方式会更稳定,未来就算它们都不在包根 了,依然无需修改引用路径。所以路径的选用,往往还是取决于场景,以及未来代码的可能走向。
那么你可能会问,为何不使用 `crate::serve_order` 的方式?额,其实也可以,不过如果你确定未来这种层级关系不会改变,那么 `super::serve_order` 的方式会更稳定,未来就算它们都不在顶层包 `crate` 了,依然无需修改引用路径。所以路径的选用,往往还是取决于场景,以及未来代码的可能走向。
## 使用 `self` 引用模块
@ -295,7 +296,7 @@ mod back_of_house {
在之前的例子中,我们所有的模块都定义在 `src/lib.rs` 中,但是当模块变多或者变大时,需要将模块放入一个单独的文件中,让代码更好维护。
现在,把 `front_of_house` 前厅分离出来,放入一个单独的文件中 `src/front_of_house.rs` :
现在,把 `front_of_house` 前厅分离出来,放入一个单独的文件 `src/front_of_house.rs` 中 :
```rust
pub mod hosting {
@ -328,4 +329,4 @@ so easy! 其实跟之前在同一个文件中也没有太大的不同, 但是
## 课后练习
> [Rust By Practice ](https://zh.practice.rs/crate-module/module.html ),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice/blob/master/solutions/crate-module/module.md)。
> [Rust By Practice ](https://zh.practice.rs/crate-module/module.html ),支持代码在线编辑和运行,并提供详细的[习题解答](https://github.com/sunface/rust-by-practice/blob/master/solutions/crate-module/module.md)。