diff --git a/listings/ch07-managing-growing-projects/listing-07-03/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-03/src/lib.rs
index 0b8a43c..783b57d 100755
--- a/listings/ch07-managing-growing-projects/listing-07-03/src/lib.rs
+++ b/listings/ch07-managing-growing-projects/listing-07-03/src/lib.rs
@@ -5,9 +5,9 @@ mod front_of_house {
}
pub fn eat_at_restaurant() {
- // Absolute path
+ // 绝对路径
crate::front_of_house::hosting::add_to_waitlist();
- // Relative path
+ // 相对路径
front_of_house::hosting::add_to_waitlist();
}
diff --git a/listings/ch07-managing-growing-projects/listing-07-05/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-05/src/lib.rs
index 05372db..7325a85 100755
--- a/listings/ch07-managing-growing-projects/listing-07-05/src/lib.rs
+++ b/listings/ch07-managing-growing-projects/listing-07-05/src/lib.rs
@@ -5,9 +5,9 @@ mod front_of_house {
}
pub fn eat_at_restaurant() {
- // Absolute path
+ // 绝对路径
crate::front_of_house::hosting::add_to_waitlist();
- // Relative path
+ // 相对路径
front_of_house::hosting::add_to_waitlist();
}
diff --git a/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs
index 7b89ee7..7063ad8 100755
--- a/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs
+++ b/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs
@@ -5,9 +5,9 @@ mod front_of_house {
}
pub fn eat_at_restaurant() {
- // Absolute path
+ // 绝对路径
crate::front_of_house::hosting::add_to_waitlist();
- // Relative path
+ // 相对路径
front_of_house::hosting::add_to_waitlist();
}
diff --git a/listings/ch07-managing-growing-projects/listing-07-09/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-09/src/lib.rs
index 92c4695..c7e7400 100755
--- a/listings/ch07-managing-growing-projects/listing-07-09/src/lib.rs
+++ b/listings/ch07-managing-growing-projects/listing-07-09/src/lib.rs
@@ -15,13 +15,13 @@ mod back_of_house {
}
pub fn eat_at_restaurant() {
- // Order a breakfast in the summer with Rye toast
+ // 在夏天订购一个黑麦土司作为早餐
let mut meal = back_of_house::Breakfast::summer("Rye");
- // Change our mind about what bread we'd like
+ // 改变注意更换想要面包的类型
meal.toast = String::from("Wheat");
println!("I'd like {} toast please", meal.toast);
- // The next line won't compile if we uncomment it; we're not allowed
- // to see or modify the seasonal fruit that comes with the meal
+ // 如果取消下一行的注释代码不能编译;
+ // 不允许查看或修改早餐附带的季节水果
// meal.seasonal_fruit = String::from("blueberries");
}
diff --git a/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md b/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md
index d6facbd..1f95c7a 100644
--- a/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md
+++ b/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md
@@ -2,11 +2,11 @@
> [ch07-00-managing-growing-projects-with-packages-crates-and-modules.md](https://github.com/rust-lang/book/blob/main/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md)
>
-> commit 879fef2345bf32751a83a9e779e0cb84e79b6d3d
+> commit 5bd82160c11a90d6d46fc37d7f3ff3e33d120763
当你编写大型程序时,组织你的代码显得尤为重要,因为你想在脑海中通晓整个程序,那几乎是不可能完成的。通过对相关功能进行分组和划分不同功能的代码,你可以清楚在哪里可以找到实现了特定功能的代码,以及在哪里可以改变一个功能的工作方式。
-到目前为止,我们编写的程序都在一个文件的一个模块中。伴随着项目的增长,你可以通过将代码分解为多个模块和多个文件来组织代码。一个包可以包含多个二进制 crate 项和一个可选的 crate 库。伴随着包的增长,你可以将包中的部分代码提取出来,做成独立的 crate,这些 crate 则作为外部依赖项。本章将会涵盖所有这些概念。对于一个由一系列相互关联的包组合而成的超大型项目,Cargo 提供了 “工作空间” 这一功能,我们将在第十四章的 “[Cargo Workspaces](ch14-03-cargo-workspaces.html)” 对此进行讲解。
+到目前为止,我们编写的程序都在一个文件的一个模块中。伴随着项目的增长,你可以通过将代码分解为多个模块和多个文件来组织代码。一个包可以包含多个二进制 crate 项和一个可选的 crate 库。伴随着包的增长,你可以将包中的部分代码提取出来,做成独立的 crate,这些 crate 则作为外部依赖项。本章将会涵盖所有这些概念。对于一个由一系列相互关联的包组合而成的超大型项目,Cargo 提供了 “工作空间” 这一功能,我们将在第十四章的 [“Cargo Workspaces”][workspaces] 对此进行讲解。
除了对功能进行分组以外,封装实现细节可以使你更高级地重用代码:你实现了一个操作后,其他的代码可以通过该代码的公共接口来进行调用,而不需要知道它是如何实现的。你在编写代码时可以定义哪些部分是其他代码可以使用的公共部分,以及哪些部分是你有权更改实现细节的私有部分。这是另一种减少你在脑海中记住项目内容数量的方法。
@@ -20,3 +20,5 @@ Rust 有许多功能可以让你管理代码的组织,包括哪些内容可以
* **路径**(*path*):一个命名例如结构体、函数或模块等项的方式
本章将会涵盖所有这些概念,讨论它们如何交互,并说明如何使用它们来管理作用域。到最后,你会对模块系统有深入的了解,并且能够像专业人士一样使用作用域!
+
+[workspaces]: ch14-03-cargo-workspaces.html
diff --git a/src/ch07-01-packages-and-crates.md b/src/ch07-01-packages-and-crates.md
index 3ccb7b8..aab9d16 100644
--- a/src/ch07-01-packages-and-crates.md
+++ b/src/ch07-01-packages-and-crates.md
@@ -2,15 +2,15 @@
> [ch07-01-packages-and-crates.md](https://github.com/rust-lang/book/blob/main/src/ch07-01-packages-and-crates.md)
>
-> commit 879fef2345bf32751a83a9e779e0cb84e79b6d3d
+> commit 53f1492a626501ea6fea6c4919a69bdb736b7dcb
-模块系统的第一部分,我们将介绍包和 crate。crate 是一个二进制项或者库。*crate root* 是一个源文件,Rust 编译器以它为起始点,并构成你的 crate 的根模块(我们将在 “[定义模块来控制作用域与私有性](https://github.com/rust-lang/book/blob/master/src/ch07-02-defining-modules-to-control-scope-and-privacy.md)” 一节深入解读)。*包*(*package*) 是提供一系列功能的一个或者多个 crate。一个包会包含有一个 *Cargo.toml* 文件,阐述如何去构建这些 crate。
+模块系统的第一部分,我们将介绍包和 crate。crate 是一个二进制项或者库。*crate root* 是一个源文件,Rust 编译器以它为起始点,并构成你的 crate 的根模块(我们将在 [“定义模块来控制作用域与私有性”][modules] 一节深入解读)。*包*(*package*) 是提供一系列功能的一个或者多个 crate。一个包会包含有一个 *Cargo.toml* 文件,阐述如何去构建这些 crate。
-包中所包含的内容由几条规则来确立。一个包中至多 **只能** 包含一个库 crate(library crate);包中可以包含任意多个二进制 crate(binary crate);包中至少包含一个 crate,无论是库的还是二进制的。
+包中所包含的内容由几条规则来确立。包中可以包含至多一个库 crate(library crate)。包中可以包含任意多个二进制 crate(binary crate),但是必须至少包含一个 crate(无论是库的还是二进制的)。
让我们来看看创建包的时候会发生什么。首先,我们输入命令 `cargo new`:
-```text
+```console
$ cargo new my-project
Created binary (application) `my-project` package
$ ls my-project
@@ -22,10 +22,13 @@ main.rs
当我们输入了这条命令,Cargo 会给我们的包创建一个 *Cargo.toml* 文件。查看 *Cargo.toml* 的内容,会发现并没有提到 *src/main.rs*,因为 Cargo 遵循的一个约定:*src/main.rs* 就是一个与包同名的二进制 crate 的 crate 根。同样的,Cargo 知道如果包目录中包含 *src/lib.rs*,则包带有与其同名的库 crate,且 *src/lib.rs* 是 crate 根。crate 根文件将由 Cargo 传递给 `rustc` 来实际构建库或者二进制项目。
-在此,我们有了一个只包含 *src/main.rs* 的包,意味着它只含有一个名为 `my-project` 的二进制 crate。如果一个包同时含有 *src/main.rs* 和 *src/lib.rs*,则它有两个 crate:一个库和一个二进制项,且名字都与包相同。通过将文件放在 *src/bin* 目录下,一个包可以拥有多个二进制 crate:每个 *src/bin* 下的文件都会被编译成一个独立的二进制 crate。
+在此,我们有了一个只包含 *src/main.rs* 的包,意味着它只含有一个名为 `my-project` 的二进制 crate。如果一个包同时含有 *src/main.rs* 和 *src/lib.rs*,则它有两个 crate:一个二进制的和一个库的,且名字都与包相同。通过将文件放在 *src/bin* 目录下,一个包可以拥有多个二进制 crate:每个 *src/bin* 下的文件都会被编译成一个独立的二进制 crate。
-一个 crate 会将一个作用域内的相关功能分组到一起,使得该功能可以很方便地在多个项目之间共享。举一个例子,我们在 [第二章](https://github.com/rust-lang/book/blob/master/src/ch02-00-guessing-game-tutorial.md#generating-a-random-number) 使用的 `rand` crate 提供了生成随机数的功能。通过将 `rand` crate 加入到我们项目的作用域中,我们就可以在自己的项目中使用该功能。`rand` crate 提供的所有功能都可以通过该 crate 的名字:`rand` 进行访问。
+一个 crate 会将一个作用域内的相关功能分组到一起,使得该功能可以很方便地在多个项目之间共享。举一个例子,我们在 [第二章][rand] 使用的 `rand` crate 提供了生成随机数的功能。通过将 `rand` crate 加入到我们项目的作用域中,我们就可以在自己的项目中使用该功能。`rand` crate 提供的所有功能都可以通过该 crate 的名字:`rand` 进行访问。
将一个 crate 的功能保持在其自身的作用域中,可以知晓一些特定的功能是在我们的 crate 中定义的还是在 `rand` crate 中定义的,这可以防止潜在的冲突。例如,`rand` crate 提供了一个名为 `Rng` 的特性(trait)。我们还可以在我们自己的 crate 中定义一个名为 `Rng` 的 `struct`。因为一个 crate 的功能是在自身的作用域进行命名的,当我们将 `rand` 作为一个依赖,编译器不会混淆 `Rng` 这个名字的指向。在我们的 crate 中,它指向的是我们自己定义的 `struct Rng`。我们可以通过 `rand::Rng` 这一方式来访问 `rand` crate 中的 `Rng` 特性(trait)。
接下来让我们来说一说模块系统!
+
+[modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html
+[rand]: ch02-00-guessing-game-tutorial.html#生成一个随机数
diff --git a/src/ch07-02-defining-modules-to-control-scope-and-privacy.md b/src/ch07-02-defining-modules-to-control-scope-and-privacy.md
index dea84d8..c8878c4 100644
--- a/src/ch07-02-defining-modules-to-control-scope-and-privacy.md
+++ b/src/ch07-02-defining-modules-to-control-scope-and-privacy.md
@@ -2,7 +2,7 @@
> [ch07-02-defining-modules-to-control-scope-and-privacy.md](https://github.com/rust-lang/book/blob/main/src/ch07-02-defining-modules-to-control-scope-and-privacy.md)
>
-> commit 34b089627cca09a73ce92a052222304bff0056e3
+> commit eb60fedc9ccd72999f9aabd82f5936ca0143dd8f
在本节,我们将讨论模块和其它一些关于模块系统的部分,如允许你命名项的 *路径*(*paths*);用来将路径引入作用域的 `use` 关键字;以及使项变为公有的 `pub` 关键字。我们还将讨论 `as` 关键字、外部包和 glob 运算符。现在,让我们把注意力放在模块上!
@@ -14,22 +14,8 @@
文件名: src/lib.rs
-```rust
-mod front_of_house {
- mod hosting {
- fn add_to_waitlist() {}
-
- fn seat_at_table() {}
- }
-
- mod serving {
- fn take_order() {}
-
- fn server_order() {}
-
- fn take_payment() {}
- }
-}
+```rust,noplayground
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs}}
```
示例 7-1:一个包含了其他内置了函数的模块的 `front_of_house` 模块
diff --git a/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md b/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md
index 973b513..5a872f1 100644
--- a/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md
+++ b/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md
@@ -1,36 +1,23 @@
## 路径用于引用模块树中的项
-> [ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md](https://github.com/rust-lang/book/blob/main/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md)
->
-> commit cc6a1ef2614aa94003566027b285b249ccf961fa
+> [ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md](https://github.com/rust-lang/book/blob/main/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md) >
+> commit 9c0fa2714859738ff73cbbb829592e4c037d7e46
来看一下 Rust 如何在模块树中找到一个项的位置,我们使用路径的方式,就像在文件系统使用路径一样。如果我们想要调用一个函数,我们需要知道它的路径。
路径有两种形式:
-* **绝对路径**(*absolute path*)从 crate 根开始,以 crate 名或者字面值 `crate` 开头。
-* **相对路径**(*relative path*)从当前模块开始,以 `self`、`super` 或当前模块的标识符开头。
+- **绝对路径**(_absolute path_)从 crate 根开始,以 crate 名或者字面值 `crate` 开头。
+- **相对路径**(_relative path_)从当前模块开始,以 `self`、`super` 或当前模块的标识符开头。
绝对路径和相对路径都后跟一个或多个由双冒号(`::`)分割的标识符。
-让我们回到示例 7-1。我们如何调用 `add_to_waitlist` 函数?还是同样的问题,`add_to_waitlist` 函数的路径是什么?在示例 7-3 中,我们通过删除一些模块和函数,稍微简化了一下我们的代码。我们在 crate 根定义了一个新函数 `eat_at_restaurant`,并在其中展示调用 `add_to_waitlist` 函数的两种方法。`eat_at_restaurant` 函数是我们 crate 库的一个公共API,所以我们使用 `pub` 关键字来标记它。在 “[使用`pub`关键字暴露路径](ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#exposing-paths-with-the-pub-keyword)” 一节,我们将详细介绍 `pub`。注意,这个例子无法编译通过,我们稍后会解释原因。
+让我们回到示例 7-1。我们如何调用 `add_to_waitlist` 函数?还是同样的问题,`add_to_waitlist` 函数的路径是什么?在示例 7-3 中,我们通过删除一些模块和函数,稍微简化了一下我们的代码。我们在 crate 根定义了一个新函数 `eat_at_restaurant`,并在其中展示调用 `add_to_waitlist` 函数的两种方法。`eat_at_restaurant` 函数是我们 crate 库的一个公共 API,所以我们使用 `pub` 关键字来标记它。在 [“使用`pub`关键字暴露路径”][pub] 一节,我们将详细介绍 `pub`。注意,这个例子无法编译通过,我们稍后会解释原因。
文件名: src/lib.rs
```rust,ignore,does_not_compile
-mod front_of_house {
- mod hosting {
- fn add_to_waitlist() {}
- }
-}
-
-pub fn eat_at_restaurant() {
- // Absolute path
- crate::front_of_house::hosting::add_to_waitlist();
-
- // Relative path
- front_of_house::hosting::add_to_waitlist();
-}
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-03/src/lib.rs}}
```
示例 7-3: 使用绝对路径和相对路径来调用 `add_to_waitlist` 函数
@@ -45,27 +32,15 @@ pub fn eat_at_restaurant() {
让我们试着编译一下示例 7-3,并查明为何不能编译!示例 7-4 展示了这个错误。
-```text
-$ cargo build
- Compiling restaurant v0.1.0 (file:///projects/restaurant)
-error[E0603]: module `hosting` is private
- --> src/lib.rs:9:28
- |
-9 | crate::front_of_house::hosting::add_to_waitlist();
- | ^^^^^^^
-
-error[E0603]: module `hosting` is private
- --> src/lib.rs:12:21
- |
-12 | front_of_house::hosting::add_to_waitlist();
- | ^^^^^^^
+```console
+{{#include ../listings/ch07-managing-growing-projects/listing-07-03/output.txt}}
```
示例 7-4: 构建示例 7-3 出现的编译器错误
错误信息说 `hosting` 模块是私有的。换句话说,我们拥有 `hosting` 模块和 `add_to_waitlist` 函数的的正确路径,但是 Rust 不让我们使用,因为它不能访问私有片段。
-模块不仅对于你组织代码很有用。他们还定义了 Rust 的 *私有性边界*(*privacy boundary*):这条界线不允许外部代码了解、调用和依赖被封装的实现细节。所以,如果你希望创建一个私有函数或结构体,你可以将其放入模块。
+模块不仅对于你组织代码很有用。他们还定义了 Rust 的 _私有性边界_(_privacy boundary_):这条界线不允许外部代码了解、调用和依赖被封装的实现细节。所以,如果你希望创建一个私有函数或结构体,你可以将其放入模块。
Rust 中默认所有项(函数、方法、结构体、枚举、模块和常量)都是私有的。父模块中的项不能使用子模块中的私有项,但是子模块中的项可以使用他们父模块中的项。这是因为子模块封装并隐藏了他们的实现详情,但是子模块可以看到他们定义的上下文。继续拿餐馆作比喻,把私有性规则想象成餐馆的后台办公室:餐馆内的事务对餐厅顾客来说是不可知的,但办公室经理可以洞悉其经营的餐厅并在其中做任何事情。
@@ -78,44 +53,20 @@ Rust 选择以这种方式来实现模块系统功能,因此默认隐藏内部
文件名: src/lib.rs
```rust,ignore,does_not_compile
-mod front_of_house {
- pub mod hosting {
- fn add_to_waitlist() {}
- }
-}
-
-pub fn eat_at_restaurant() {
- // Absolute path
- crate::front_of_house::hosting::add_to_waitlist();
-
- // Relative path
- front_of_house::hosting::add_to_waitlist();
-}
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-05/src/lib.rs}}
```
示例 7-5: 使用 `pub` 关键字声明 `hosting` 模块使其可在 `eat_at_restaurant` 使用
不幸的是,示例 7-5 的代码编译仍然有错误,如示例 7-6 所示。
-```text
-$ cargo build
- Compiling restaurant v0.1.0 (file:///projects/restaurant)
-error[E0603]: function `add_to_waitlist` is private
- --> src/lib.rs:9:37
- |
-9 | crate::front_of_house::hosting::add_to_waitlist();
- | ^^^^^^^^^^^^^^^
-
-error[E0603]: function `add_to_waitlist` is private
- --> src/lib.rs:12:30
- |
-12 | front_of_house::hosting::add_to_waitlist();
- | ^^^^^^^^^^^^^^^
+```console
+{{#include ../listings/ch07-managing-growing-projects/listing-07-05/output.txt}}
```
示例 7-6: 构建示例 7-5 出现的编译器错误
-发生了什么?在 `mod hosting` 前添加了 `pub` 关键字,使其变成公有的。伴随着这种变化,如果我们可以访问 `front_of_house`,那我们也可以访问 `hosting`。但是 `hosting` 的 *内容*(*contents*) 仍然是私有的;这表明使模块公有并不使其内容也是公有的。模块上的 `pub` 关键字只允许其父模块引用它。
+发生了什么?在 `mod hosting` 前添加了 `pub` 关键字,使其变成公有的。伴随着这种变化,如果我们可以访问 `front_of_house`,那我们也可以访问 `hosting`。但是 `hosting` 的 _内容_(_contents_) 仍然是私有的;这表明使模块公有并不使其内容也是公有的。模块上的 `pub` 关键字只允许其父模块引用它。
示例 7-6 中的错误说,`add_to_waitlist` 函数是私有的。私有性规则不但应用于模块,还应用于结构体、枚举、函数和方法。
@@ -123,21 +74,8 @@ error[E0603]: function `add_to_waitlist` is private
文件名: src/lib.rs
-```rust
-mod front_of_house {
- pub mod hosting {
- pub fn add_to_waitlist() {}
- }
-}
-
-pub fn eat_at_restaurant() {
- // Absolute path
- crate::front_of_house::hosting::add_to_waitlist();
-
- // Relative path
- front_of_house::hosting::add_to_waitlist();
-}
-# fn main() {}
+```rust,noplayground,test_harness
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs}}
```
示例 7-7: 为 `mod hosting`
@@ -158,18 +96,8 @@ pub fn eat_at_restaurant() {
文件名: src/lib.rs
-```rust
-fn serve_order() {}
-
-mod back_of_house {
- fn fix_incorrect_order() {
- cook_order();
- super::serve_order();
- }
-
- fn cook_order() {}
-}
-# fn main() {}
+```rust,noplayground,test_harness
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs}}
```
示例 7-8: 使用以 `super` 开头的相对路径从父目录开始调用函数
@@ -182,34 +110,8 @@ mod back_of_house {
文件名: src/lib.rs
-```rust
-mod back_of_house {
- pub struct Breakfast {
- pub toast: String,
- seasonal_fruit: String,
- }
-
- impl Breakfast {
- pub fn summer(toast: &str) -> Breakfast {
- Breakfast {
- toast: String::from(toast),
- seasonal_fruit: String::from("peaches"),
- }
- }
- }
-}
-
-pub fn eat_at_restaurant() {
- // Order a breakfast in the summer with Rye toast
- let mut meal = back_of_house::Breakfast::summer("Rye");
- // Change our mind about what bread we'd like
- meal.toast = String::from("Wheat");
- println!("I'd like {} toast please", meal.toast);
-
- // The next line won't compile if we uncomment it; we're not allowed
- // to see or modify the seasonal fruit that comes with the meal
- // meal.seasonal_fruit = String::from("blueberries");
-}
+```rust,noplayground
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-09/src/lib.rs}}
```
示例 7-9: 带有公有和私有字段的结构体
@@ -222,18 +124,8 @@ pub fn eat_at_restaurant() {
文件名: src/lib.rs
-```rust
-mod back_of_house {
- pub enum Appetizer {
- Soup,
- Salad,
- }
-}
-
-pub fn eat_at_restaurant() {
- let order1 = back_of_house::Appetizer::Soup;
- let order2 = back_of_house::Appetizer::Salad;
-}
+```rust,noplayground
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-10/src/lib.rs}}
```
示例 7-10: 设计公有枚举,使其所有成员公有
@@ -241,3 +133,5 @@ pub fn eat_at_restaurant() {
因为我们创建了名为 `Appetizer` 的公有枚举,所以我们可以在 `eat_at_restaurant` 中使用 `Soup` 和 `Salad` 成员。如果枚举成员不是公有的,那么枚举会显得用处不大;给枚举的所有成员挨个添加 `pub` 是很令人恼火的,因此枚举成员默认就是公有的。结构体通常使用时,不必将它们的字段公有化,因此结构体遵循常规,内容全部是私有的,除非使用 `pub` 关键字。
还有一种使用 `pub` 的场景我们还没有涉及到,那就是我们最后要讲的模块功能:`use` 关键字。我们将先单独介绍 `use`,然后展示如何结合使用 `pub` 和 `use`。
+
+[pub]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#使用-pub-关键字暴露路径
diff --git a/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md b/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md
index be7177f..9089eae 100644
--- a/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md
+++ b/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md
@@ -2,7 +2,7 @@
> [ch07-04-bringing-paths-into-scope-with-the-use-keyword.md](https://github.com/rust-lang/book/blob/main/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md)
>
-> commit 6d3e76820418f2d2bb203233c61d90390b5690f1
+> commit 2d605f66b3d891dea0a2f684ece508aa2282b854
到目前为止,似乎我们编写的用于调用函数的路径都很冗长且重复,并不方便。例如,示例 7-7 中,无论我们选择 `add_to_waitlist` 函数的绝对路径还是相对路径,每次我们想要调用 `add_to_waitlist` 时,都必须指定`front_of_house` 和 `hosting`。幸运的是,有一种方法可以简化这个过程。我们可以使用 `use` 关键字将路径一次性引入作用域,然后调用该路径中的项,就如同它们是本地项一样。
@@ -10,21 +10,8 @@
文件名: src/lib.rs
-```rust
-mod front_of_house {
- pub mod hosting {
- pub fn add_to_waitlist() {}
- }
-}
-
-use crate::front_of_house::hosting;
-
-pub fn eat_at_restaurant() {
- hosting::add_to_waitlist();
- hosting::add_to_waitlist();
- hosting::add_to_waitlist();
-}
-# fn main() {}
+```rust,noplayground,test_harness
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs}}
```
示例 7-11: 使用 `use` 将模块引入作用域
@@ -35,21 +22,8 @@ pub fn eat_at_restaurant() {
文件名: src/lib.rs
-```rust
-mod front_of_house {
- pub mod hosting {
- pub fn add_to_waitlist() {}
- }
-}
-
-use front_of_house::hosting;
-
-pub fn eat_at_restaurant() {
- hosting::add_to_waitlist();
- hosting::add_to_waitlist();
- hosting::add_to_waitlist();
-}
-# fn main() {}
+```rust,noplayground,test_harness
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs}}
```
示例 7-12: 使用 `use` 和相对路径将模块引入作用域
@@ -60,21 +34,8 @@ pub fn eat_at_restaurant() {
文件名: src/lib.rs
-```rust
-mod front_of_house {
- pub mod hosting {
- pub fn add_to_waitlist() {}
- }
-}
-
-use crate::front_of_house::hosting::add_to_waitlist;
-
-pub fn eat_at_restaurant() {
- add_to_waitlist();
- add_to_waitlist();
- add_to_waitlist();
-}
-# fn main() {}
+```rust,noplayground,test_harness
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs}}
```
示例 7-13: 使用 `use` 将 `add_to_waitlist` 函数引入作用域,这并不符合习惯
@@ -86,12 +47,7 @@ pub fn eat_at_restaurant() {
文件名: src/main.rs
```rust
-use std::collections::HashMap;
-
-fn main() {
- let mut map = HashMap::new();
- map.insert(1, 2);
-}
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-14/src/main.rs}}
```
示例 7-14: 将 `HashMap` 引入作用域的习惯用法
@@ -102,19 +58,8 @@ fn main() {
文件名: src/lib.rs
-```rust
-use std::fmt;
-use std::io;
-
-fn function1() -> fmt::Result {
- // --snip--
-# Ok(())
-}
-
-fn function2() -> io::Result<()> {
- // --snip--
-# Ok(())
-}
+```rust,noplayground
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-15/src/lib.rs:here}}
```
示例 7-15: 使用父模块将两个具有相同名称的类型引入同一作用域
@@ -127,19 +72,8 @@ fn function2() -> io::Result<()> {
文件名: src/lib.rs
-```rust
-use std::fmt::Result;
-use std::io::Result as IoResult;
-
-fn function1() -> Result {
- // --snip--
-# Ok(())
-}
-
-fn function2() -> IoResult<()> {
- // --snip--
-# Ok(())
-}
+```rust,noplayground
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-16/src/lib.rs:here}}
```
示例 7-16: 使用 `as` 关键字重命名引入作用域的类型
@@ -154,21 +88,8 @@ fn function2() -> IoResult<()> {
文件名: src/lib.rs
-```rust
-mod front_of_house {
- pub mod hosting {
- pub fn add_to_waitlist() {}
- }
-}
-
-pub use crate::front_of_house::hosting;
-
-pub fn eat_at_restaurant() {
- hosting::add_to_waitlist();
- hosting::add_to_waitlist();
- hosting::add_to_waitlist();
-}
-# fn main() {}
+```rust,noplayground,test_harness
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs}}
```
示例 7-17: 通过 `pub use` 使名称可引入任何代码的作用域中
@@ -184,8 +105,7 @@ pub fn eat_at_restaurant() {
文件名: Cargo.toml
```toml
-[dependencies]
-rand = "0.5.5"
+{{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:9:}}
```
在 *Cargo.toml* 中加入 `rand` 依赖告诉了 Cargo 要从 [crates.io](https://crates.io) 下载 `rand` 和其依赖,并使其可在项目代码中使用。
@@ -193,11 +113,7 @@ rand = "0.5.5"
接着,为了将 `rand` 定义引入项目包的作用域,我们加入一行 `use` 起始的包名,它以 `rand` 包名开头并列出了需要引入作用域的项。回忆一下第二章的 “生成一个随机数” 部分,我们曾将 `Rng` trait 引入作用域并调用了 `rand::thread_rng` 函数:
```rust,ignore
-use rand::Rng;
-
-fn main() {
- let secret_number = rand::thread_rng().gen_range(1, 101);
-}
+{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs:ch07-04}}
```
[crates.io](https://crates.io) 上有很多 Rust 社区成员发布的包,将其引入你自己的项目都需要一道相同的步骤:在 *Cargo.toml* 列出它们并通过 `use` 将其中定义的项引入项目包的作用域中。
@@ -216,19 +132,16 @@ use std::collections::HashMap;
文件名: src/main.rs
-```rust
-use std::cmp::Ordering;
-use std::io;
-// ---snip---
+```rust,ignore
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs:here}}
```
相反,我们可以使用嵌套路径将相同的项在一行中引入作用域。这么做需要指定路径的相同部分,接着是两个冒号,接着是大括号中的各自不同的路径部分,如示例 7-18 所示。
文件名: src/main.rs
-```rust
-use std::{cmp::Ordering, io};
-// ---snip---
+```rust,ignore
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-18/src/main.rs:here}}
```
示例 7-18: 指定嵌套的路径在一行中将多个带有相同前缀的项引入作用域
@@ -239,9 +152,8 @@ use std::{cmp::Ordering, io};
文件名: src/lib.rs
-```rust
-use std::io;
-use std::io::Write;
+```rust,noplayground
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-19/src/lib.rs}}
```
示例 7-19: 通过两行 `use` 语句引入两个路径,其中一个是另一个的子路径
@@ -250,8 +162,8 @@ use std::io::Write;
文件名: src/lib.rs
-```rust
-use std::io::{self, Write};
+```rust,noplayground
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-20/src/lib.rs}}
```
示例 7-20: 将示例 7-19 中部分重复的路径合并为一个 `use` 语句
@@ -269,3 +181,6 @@ use std::collections::*;
这个 `use` 语句将 `std::collections` 中定义的所有公有项引入当前作用域。使用 glob 运算符时请多加小心!Glob 会使得我们难以推导作用域中有什么名称和它们是在何处定义的。
glob 运算符经常用于测试模块 `tests` 中,这时会将所有内容引入作用域;我们将在第十一章 “如何编写测试” 部分讲解。glob 运算符有时也用于 prelude 模式;查看 [标准库中的文档](https://doc.rust-lang.org/std/prelude/index.html#other-preludes) 了解这个模式的更多细节。
+
+[rand]: ch02-00-guessing-game-tutorial.html#生成一个随机数
+[writing-tests]: ch11-01-writing-tests.html#如何编写测试
diff --git a/src/ch07-05-separating-modules-into-different-files.md b/src/ch07-05-separating-modules-into-different-files.md
index e24da7b..3f8ea8d 100644
--- a/src/ch07-05-separating-modules-into-different-files.md
+++ b/src/ch07-05-separating-modules-into-different-files.md
@@ -2,7 +2,7 @@
> [ch07-05-separating-modules-into-different-files.md](https://github.com/rust-lang/book/blob/main/src/ch07-05-separating-modules-into-different-files.md)
>
-> commit a5a5bf9d6ea5763a9110f727911a21da854b1d90
+> commit d5584fb1efeaf8aadfc7caf516df7f1ca0820ceb
到目前为止,本章所有的例子都在一个文件中定义多个模块。当模块变得更大时,你可能想要将它们的定义移动到单独的文件中,从而使代码更容易阅读。
@@ -11,15 +11,7 @@
文件名: src/lib.rs
```rust,ignore
-mod front_of_house;
-
-pub use crate::front_of_house::hosting;
-
-pub fn eat_at_restaurant() {
- hosting::add_to_waitlist();
- hosting::add_to_waitlist();
- hosting::add_to_waitlist();
-}
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs}}
```
示例 7-21: 声明 `front_of_house` 模块,其内容将位于 *src/front_of_house.rs*
@@ -28,10 +20,8 @@ pub fn eat_at_restaurant() {
文件名: src/front_of_house.rs
-```rust
-pub mod hosting {
- pub fn add_to_waitlist() {}
-}
+```rust,ignore
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-21-and-22/src/front_of_house.rs}}
```
示例 7-22: 在 *src/front_of_house.rs* 中定义 `front_of_house`
@@ -41,16 +31,16 @@ pub mod hosting {
文件名: src/front_of_house.rs
-```rust
-pub mod hosting;
+```rust,ignore
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house.rs}}
```
接着我们创建一个 *src/front_of_house* 目录和一个包含 `hosting` 模块定义的 *src/front_of_house/hosting.rs* 文件:
文件名: src/front_of_house/hosting.rs
-```
-pub fn add_to_waitlist() {}
+```rust
+{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house/hosting.rs}}
```
模块树依然保持相同,`eat_at_restaurant` 中的函数调用也无需修改继续保持有效,即便其定义存在于不同的文件中。这个技巧让你可以在模块代码增长时,将它们移动到新文件中。