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` 中的函数调用也无需修改继续保持有效,即便其定义存在于不同的文件中。这个技巧让你可以在模块代码增长时,将它们移动到新文件中。