update: 补全新版ch07-03的翻译

pull/345/head
shengurun 5 years ago
parent d98eb5d71b
commit f067373618

@ -149,3 +149,95 @@ pub fn eat_at_restaurant() {
在绝对路径,我们从 `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`,路径其余的部分也是有效的,因此函数调用也是有效的!
## 使用 `super` 起始的相对路径
我们还可以使用 `super` 开头来构建从父模块开始的相对路径。这么做类似于文件系统中以 `..` 开头的语法。我们为什么要这样做呢?
考虑一下示例 7-8 中的代码,它模拟了厨师更正了一个错误订单,并亲自将其提供给客户的情况。`fix_incorrect_order`函数通过指定的 `super` 起始的 `server_order` 路径,来调用 `server_order`函数:
<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() {}
```
<span class="caption">示例 7-8: 使用以 `super` 开头的相对路径从父目录开始调用函数</span>
`fix_incorrect_order` 函数在 `back_of_house` 模块中,所以我们可以使用 `super` 进入 `back_of_house` 父模块,也就是本例中的 `crate` 根。在这里,我们可以找到`serve_order`。成功!我们认为`back_of_house`模块和`server_order`函数之间可能具有某种关联关系,并且,如果我们要重新组织这个 crate 的模块树,需要一起移动它们。因此,我们使用 `super` ,这样一来,如果这些代码被移动到了其他模块,我们只需要更新很少的代码。
## 创建公有的结构体和枚举
我们还可以使用 `pub` 来设计公有的结构体和枚举,不过有一些额外的细节需要注意。如果我们在一个结构体定义的前面使用了 `pub` ,这个结构体会变成公有的,但是这个结构体的字段仍然是私有的。我们可以根据情况决定每个字段是否公有。在示例 7-9 中,我们定义了一个公有结构体 `back_of_hous:Breakfast`,其中有一个公有字段 `toast` 和私有字段 `seasonal_fruit`。这个例子模拟的情况是,在一家餐馆中,顾客可以选择随餐附赠的面包类型,但是厨师会根据季节和库存情况来决定随餐搭配的水果。餐馆可用的水果变化是很快的,所以顾客不能选择水果,甚至无法看到他们将会得到什么水果。
<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");
}
```
<span class="caption">示例 7-9: 带有公有和私有字段的结构体</span>
因为 `back_of_house::Breakfast`结构体的 `toast` 字段是公有的,所以我们可以在 `eat_at_restaurant` 中使用点号来随意的读写 `toast` 字段。注意,我们不能在 `eat_at_restaurant` 中使用 `seasonal_fruit` 字段,因为 `seasonal_fruit` 是私有的。尝试去除那一行修改 `seasonal_fruit` 字段值的代码的注释,看看你会得到什么错误!
还请注意一点,因为 `back_of_house::Breakfast` 具有私有字段,所以这个结构体需要提供一个公共的关联函数来构造示例 `Breakfast` (这里我们命名为 `summer`)。如果 `Breakfast` 没有这样的函数,我们将无法在 `eat_at_restaurant`中创建 `Breakfast` 实例,因为我们不能在 `eat_at_restaurant` 中设置私有字段 `seasonal_fruit` 的值。
与之相反,如果我们将枚举设为公有,则它的所有成员都将变为公有。我们只需要在 `enum` 关键字前面加上 `pub`,就像示例 7-10 展示的那样。
<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;
}
```
<span class="caption">示例 7-10: 设计公有枚举,使其所有成员公有</span>
因为我们创建了名为 `Appetizer` 的公有枚举,所以我们可以在 `eat_at_restaurant` 中使用 `Soup``Salad` 成员。如果枚举成员不是公有的,那么枚举会显得用处不大;给枚举的所有成员挨个添加 `pub` 是很令人恼火的,因此枚举成员默认就是公有的。结构体通常使用时,不必将它们的字段公有化,因此结构体遵循常规,内容全部是私有的,除非使用 `pub` 关键字。
还有一种使用 `pub` 的场景我们还没有涉及到,那就是我们最后要讲的模块功能:`use` 关键字。我们将先单独介绍 `use`,然后展示如何结合使用 `pub``use`

Loading…
Cancel
Save