mirror of
https://github.com/rust-lang-cn/book-cn.git
synced 2025-01-23 07:20:20 +08:00
对 ch07-03 文件的内容更新
This commit is contained in:
parent
8a102fc80e
commit
07f49520e5
@ -24,9 +24,5 @@ note: the module `hosting` is defined here
|
||||
2 | mod hosting {
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0603`.
|
||||
error: could not compile `restaurant`
|
||||
|
||||
To learn more, run the command again with --verbose.
|
||||
error: could not compile `restaurant` due to 2 previous errors
|
||||
|
@ -24,9 +24,5 @@ note: the function `add_to_waitlist` is defined here
|
||||
3 | fn add_to_waitlist() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0603`.
|
||||
error: could not compile `restaurant`
|
||||
|
||||
To learn more, run the command again with --verbose.
|
||||
error: could not compile `restaurant` due to 2 previous errors
|
||||
|
@ -4,36 +4,24 @@
|
||||
|
||||
路径有两种形式:
|
||||
|
||||
* **绝对路径**(*absolute path*)从 crate 根开始,以 crate 名或者字面值 `crate` 开头。
|
||||
* **绝对路径**(*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]<!-- ignore -->一节,我们将详细介绍 `pub`。注意,这个例子无法编译通过,我们稍后会解释原因。
|
||||
|
||||
<span class="filename">文件名: src/lib.rs</span>
|
||||
|
||||
```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}}
|
||||
```
|
||||
|
||||
<span class="caption">示例 7-3: 使用绝对路径和相对路径来调用 `add_to_waitlist` 函数</span>
|
||||
|
||||
第一种方式,我们在 `eat_at_restaurant` 中调用 `add_to_waitlist` 函数,使用的是绝对路径。`add_to_waitlist` 函数与 `eat_at_restaurant` 被定义在同一 crate 中,这意味着我们可以使用 `crate` 关键字为起始的绝对路径。
|
||||
|
||||
在 `crate` 后面,我们持续地嵌入模块,直到我们找到 `add_to_waitlist`。你可以想象出一个相同结构的文件系统,我们通过指定路径 `/front_of_house/hosting/add_to_waitlist` 来执行 `add_to_waitlist` 程序。我们使用 `crate` 从 crate 根开始就类似于在 shell 中使用 `/` 从文件系统根开始。
|
||||
在 `crate` 后面,我们持续地嵌入模块,直到我们找到 `add_to_waitlist`。你可以想象出一个相同结构的文件系统,我们通过指定路径 `/front_of_house/hosting/add_to_waitlist` 来执行 `add_to_waitlist` 程序。我们使用 `crate` 从 crate 根部开始就类似于在 shell 中使用 `/` 从文件系统根开始。
|
||||
|
||||
第二种方式,我们在 `eat_at_restaurant` 中调用 `add_to_waitlist`,使用的是相对路径。这个路径以 `front_of_house` 为起始,这个模块在模块树中,与 `eat_at_restaurant` 定义在同一层级。与之等价的文件系统路径就是 `front_of_house/hosting/add_to_waitlist`。以名称为起始,意味着该路径是相对路径。
|
||||
|
||||
@ -41,20 +29,8 @@ 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}}
|
||||
```
|
||||
|
||||
<span class="caption">示例 7-4: 构建示例 7-3 出现的编译器错误</span>
|
||||
@ -74,44 +50,20 @@ Rust 选择以这种方式来实现模块系统功能,因此默认隐藏内部
|
||||
<span class="filename">文件名: src/lib.rs</span>
|
||||
|
||||
```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}}
|
||||
```
|
||||
|
||||
<span class="caption">示例 7-5: 使用 `pub` 关键字声明 `hosting` 模块使其可在 `eat_at_restaurant` 使用</span>
|
||||
|
||||
不幸的是,示例 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}}
|
||||
```
|
||||
|
||||
<span class="caption">示例 7-6: 构建示例 7-5 出现的编译器错误</span>
|
||||
|
||||
发生了什么?在 `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` 函数是私有的。私有性规则不但应用于模块,还应用于结构体、枚举、函数和方法。
|
||||
|
||||
@ -119,21 +71,8 @@ error[E0603]: function `add_to_waitlist` is private
|
||||
|
||||
<span class="filename">文件名: src/lib.rs</span>
|
||||
|
||||
```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}}
|
||||
```
|
||||
|
||||
<span class="caption">示例 7-7: 为 `mod hosting`
|
||||
@ -142,9 +81,9 @@ pub fn eat_at_restaurant() {
|
||||
|
||||
现在代码可以编译通过了!让我们看看绝对路径和相对路径,并根据私有性规则,再检查一下为什么增加 `pub` 关键字使得我们可以在 `add_to_waitlist` 中调用这些路径。
|
||||
|
||||
在绝对路径,我们从 `crate`,也就是 crate 根开始。然后 crate 根中定义了 `front_of_house` 模块。`front_of_house` 模块不是公有的,不过因为 `eat_at_restaurant` 函数与 `front_of_house` 定义于同一模块中(即,`eat_at_restaurant` 和 `front_of_house` 是兄弟),我们可以从 `eat_at_restaurant` 中引用 `front_of_house`。接下来是使用 `pub` 标记的 `hosting` 模块。我们可以访问 `hosting` 的父模块,所以可以访问 `hosting`。最后,`add_to_waitlist` 函数被标记为 `pub` ,我们可以访问其父模块,所以这个函数调用是有效的!
|
||||
在绝对路径,我们从 `crate`,也就是 crate 根部开始。然后 crate 根部中定义了 `front_of_house` 模块。`front_of_house` 模块不是公有的,不过因为 `eat_at_restaurant` 函数与 `front_of_house` 定义于同一模块中(即,`eat_at_restaurant` 和 `front_of_house` 是兄弟),我们可以从 `eat_at_restaurant` 中引用 `front_of_house`。接下来是使用 `pub` 标记的 `hosting` 模块。我们可以访问 `hosting` 的父模块,所以可以访问 `hosting`。最后,`add_to_waitlist` 函数被标记为 `pub` ,我们可以访问其父模块,所以这个函数调用是有效的!
|
||||
|
||||
在相对路径,其逻辑与绝对路径相同,除了第一步:不同于从 crate 根开始,路径从 `front_of_house` 开始。`front_of_house` 模块与 `eat_at_restaurant` 定义于同一模块,所以从 `eat_at_restaurant` 中开始定义的该模块相对路径是有效的。接下来因为 `hosting` 和 `add_to_waitlist` 被标记为 `pub`,路径其余的部分也是有效的,因此函数调用也是有效的!
|
||||
在相对路径,其逻辑与绝对路径相同,除了第一步:不同于从 crate 根部开始,路径从 `front_of_house` 开始。`front_of_house` 模块与 `eat_at_restaurant` 定义于同一模块,所以从 `eat_at_restaurant` 中开始定义的该模块相对路径是有效的。接下来因为 `hosting` 和 `add_to_waitlist` 被标记为 `pub`,路径其余的部分也是有效的,因此函数调用也是有效的!
|
||||
|
||||
### 使用 `super` 起始的相对路径
|
||||
|
||||
@ -154,18 +93,8 @@ pub fn eat_at_restaurant() {
|
||||
|
||||
<span class="filename">文件名: src/lib.rs</span>
|
||||
|
||||
```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}}
|
||||
```
|
||||
|
||||
<span class="caption">示例 7-8: 使用以 `super` 开头的相对路径从父目录开始调用函数</span>
|
||||
@ -178,34 +107,8 @@ mod back_of_house {
|
||||
|
||||
<span class="filename">文件名: src/lib.rs</span>
|
||||
|
||||
```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}}
|
||||
```
|
||||
|
||||
<span class="caption">示例 7-9: 带有公有和私有字段的结构体</span>
|
||||
@ -218,18 +121,8 @@ pub fn eat_at_restaurant() {
|
||||
|
||||
<span class="filename">文件名: src/lib.rs</span>
|
||||
|
||||
```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}}
|
||||
```
|
||||
|
||||
<span class="caption">示例 7-10: 设计公有枚举,使其所有成员公有</span>
|
||||
@ -237,3 +130,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-关键字暴露路径
|
||||
|
Loading…
Reference in New Issue
Block a user