Updated src/packages_crates_and_modules/separating_modules.md'.

This commit is contained in:
Hector PENG
2026-03-16 10:43:26 +08:00
parent 6738201e96
commit 8d7c95bf8b
4 changed files with 35 additions and 35 deletions

View File

@@ -0,0 +1,2 @@
pub mod hosting;

View File

@@ -0,0 +1 @@
pub fn add_to_waitlist() {}

View File

@@ -1,13 +1,7 @@
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
use crate::front_of_house::hosting;
mod front_of_house;
pub mod customer {
use super::hosting;
use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();

View File

@@ -1,12 +1,13 @@
# 拆分模组为不同文件
到目前为止,章的所有示例都把多个模组,定义在一个文件中。当模组变大时,咱们就会想要把他们的定义,移入到单独文件中,这样代码更容易浏览。
到目前为止,这一章的所有示例都在一个文件中定义了多个模组。当模组变大时,咱们就可能希望迁移他们的定义到单独文件,使代码更易于导览。
例如,我们来从 [清单 7-17](./the_use_keyword.md#listing_7-17) 中,包含了多个餐厅模组的代码开始。我们将把这些模组提取到一些文件中,而不是把所有模组都定义在代码箱的根文件。在本例中,代码箱的根文件为 `src/lib.rs`,但这一过程也适用于根文件为 `src/main.rs` 的二进制代码箱。
例如,我们来从 [清单 7-17](./the_use_keyword.md#listing_7-17) 中有着多个餐厅模组的代码开始。我们将提取模组到文件中,而不是让全部模组都定义在代码箱的根文件。在这一情形下,代码箱的根文件为 `src/lib.rs`,但这一过程也适用于根文件为 `src/main.rs` 的二进制代码箱。
首先,我们将 `front_of_house` 这个模组提取到他自己的文件。请移除 `front_of_house` 模组花括号内的代码,只留下 `mod front_of_house;` 这个声明,这样 `src/lib.rs` 文件包含下面清单 7-21 所示的代码。请注意,在创建清单 7-22 中的 `src/front_of_house.rs` 文件前,这段代码将不编译。
首先,我们将提取 `front_of_house` 模组到他自己的文件。请移除 `front_of_house` 模组花括号内的代码,只留下 `mod front_of_house;` 声明,以便 `src/lib.rs` 文件包含下面清单 7-21 所示的代码。请注意,在我们创建清单 7-22 中的 `src/front_of_house.rs` 文件前,这段代码将不编译。
<a name="listing_7-21"></a>
文件名:`src/lib.rs`
```rust
@@ -19,11 +20,12 @@ pub fn eat_at_restaurant() {
}
```
*清单 7-21:声明出其模组代码主体,将位于 `src/front_of_house.rs` 中的 `front_of_house` 模组*
**清单 7-21**:声明`front_of_house` 模组,其主体将位于 `src/front_of_house.rs`
接下来,将原先花括符中的代码放入一个名为 `src/front_of_house.rs` 的新文件中,如下清单 7-22 所示。编译器之所以知道要在这个文件中查找,因为他在代码箱根中,看到了名为 `front_of_house` 的模组声明。
接下来,将曾在那个花括符中的代码放入名为 `src/front_of_house.rs` 的新文件中,如下清单 7-22 所示。编译器知道要在这个文件中查找,因为他在代码箱根中到了名为 `front_of_house` 的模组声明。
<a name="listing_7-22"></a>
文件名:`src/front_of_house.rs`
```rust
@@ -32,13 +34,13 @@ pub mod hosting {
}
```
*清单 7-22`src/front_of_house.rs` 中 `front_of_house` 模组内的定义*
**清单 7-22**`src/front_of_house.rs``front_of_house` 模组内的定义
请注意,咱们模组树中,咱们只需使用 `mod` 声明加载某个文件 *一次*。一旦编译器知道了该文件项目的一部分(且编译器会因咱们放置 `mod` 语句位置,而知道代码位处模组树中何处),咱们项目中的其他文件,就应能使用 [“引用模组树中某个项目的路径”](./paths.md) 小节中介绍的到其声明处的路径,引用该加载文件的代码。换句话说,`mod` *不是* 咱们在其他编程语言中,可能会看到的 “包含” 操作。
请注意,咱们只需在模组树中使用 `mod` 声明加载文件 *一次*。一旦编译器知道了该文件属于项目的一部分(并由于咱们放置 `mod` 语句之处而知道代码模组树中何处),咱们项目中的其他文件,应使用其被声明处的路径来引用已加载文件的代码,如同 [“引用模组树中项目的路径”](./paths.md) 小节中介绍的。换句话说,`mod` *不是* 咱们可能已在其他编程语言中看到的 “包含include” 操作。
接下来,我们将 `hosting` 模组提取到他自己的文件。这个过程略有不同,因为 `hosting``front_of_house` 的一个子模组,而不是根模组。我们将把 `hosting` 的文件,放到一个模组树中的以其祖先命名的新目录中,在此情形下即为 `src/front_of_house`
接下来,我们将提取 `hosting` 模组到他自己的文件。这个过程略有不同,因为 `hosting``front_of_house`,而非根模组的子模组。我们将把 `hosting` 的文件放在一个新的目录中,该目录将以模组树中他的父辈命名,在此情形下即为 `src/front_of_house`
要开始迁移 `hosting`,我们就要将 `src/front_of_house.rs`,修改为只包含 `hosting` 模组的声明:
要开始迁移 `hosting`,我们修改 `src/front_of_house.rs` 为只包含 `hosting` 模组的声明:
文件名:`src/front_of_house.rs`
@@ -46,7 +48,8 @@ pub mod hosting {
pub mod hosting;
```
然后,我们创建一个 `src/front_of_house` 目录及一个存放 `hosting` 模组中所定义内容的 `hosting.rs` 文件
然后,我们创建一个 `src/front_of_house` 目录及一个 `hosting.rs` 文件,来包含构造于 `hosting` 模组中的定义
文件名:`src/front_of_house/hosting.rs`
@@ -54,34 +57,34 @@ pub mod hosting;
pub fn add_to_waitlist() {}
```
如果我们将 `hosting.rs` 文件放在 `src` 目录下,编译器就会期望 `hosting.rs` 的代码,属于在代码箱根中声明的 `hosting` 模组,而非作`front_of_house` 模组子模组声明的。确定哪些文件属于哪个模组代码的编译器规则,意味着目录和文件结构,会与模组树更加一致
相反若我们放置 `hosting.rs` `src` 目录下,编译器就会期望 `hosting` 模组中的 `hosting.rs` 代码被声明于代码箱根中,而不是声明`front_of_house` 模组子模组。编译器关于 “检查哪些文件以获取哪些模组代码规则,意味着目录和文件会紧密地匹配模组树
> **备用文件路径**
>
> 到目前为止,我们已介绍了 Rust 编译器所使用的最常见文件路径,但 Rust 还支持一种较的文件路径风格。对于代码箱根中声明的一个名为 `front_of_house` 模组,编译器将在以下位置查找该模组的代码:
- `src/front_of_house.rs`(即这里讲到的);
- `src/front_of_house/mod.rs`(较早样式,仍被支持的路径)。
> 对于 `front_of_house` 子模组的一个名为 `hosting` 的模组,编译器将在以下位置查找该模组的代码:
- `src/front_of_house/hosting.rs`(即这里讲到的);
- `src/front_of_house/hosting/mod.rs`(较早样式,仍被支持的路径)。
> 若咱们对同一模组同时使用这两种样式,咱们将得到一个编译器报错。在同一个项目中对不同模组混合使用这两种样式是允许的,但这可能会让浏览咱们项目的人感到困惑。
> 到目前为止,我们已介绍了 Rust 编译器用到的最惯用的文件路径,但 Rust 还支持一种较的文件路径样式。对于声明于代码箱根中名为 `front_of_house` 模组,编译器将在以下位置查找该模组的代码:
>
> 使用名为 `mod.rs` 文件样式的主要缺点,是咱们的项目可能会产生大量名为 `mod.rs` 的文件,当咱们在咱们的编辑器中同时打开这些文件时,这就可能造成混淆。
> - `src/front_of_house.rs`(我们介绍的);
> - `src/front_of_house/mod.rs`(较早样式,仍受支持的路径)。
>
> 对于名为 `hosting` 属于 `front_of_house` 子模组的模组,编译器将在以下位置查找该模组的代码:
>
> - `src/front_of_house/hosting.rs`(我们介绍的);
> - `src/front_of_house/hosting/mod.rs`(较早样式,仍受支持的路径)。
>
> 若咱们对同一模组使用两种样式,咱们将得到一个编译器报错。虽然在同一项目中针对不同模组混合使用两种样式是允许的,但这可能会让浏览咱们项目的人感到困惑。
>
> 使用名为 `mod.rs` 文件的样式的主要缺点是,咱们的项目最终会有大量名为 `mod.rs` 的文件,当咱们同时在编辑器中打开他们时,这会造成混淆。
我们已各个模组的代码移至独立文件中,同时模组树保持不变。`eat_at_restaurant` 中的函数调用在无需任何修改下就将正常工作,尽管这些函数的定义现在位于别的文件中。随着模组规模扩大,这种技术允许咱们将其迁移至新文件。
我们已经迁移各个模组的代码到单独文件,而模组树保持不变。`eat_at_restaurant` 中的函数调用在无需任何修改下仍将有效,即使定义位于不同文件。这一技巧允许咱们在模组大小增加时,迁移他们到新的文件。
留意 `src/lib.rs` 中的 `pub use crate::front_of_house::hosting` 这个语句没有改变,`use` 语句对哪些文件被作为代码箱部分而被编译也没有任何影响。其中的 `mod` 关键字声明了这些模组,同时 Rust 会在与模组同名的文件中查找要放入该模组的代码。
注意,`src/lib.rs` 中的 `pub use crate::front_of_house::hosting` 同样未曾改变,`use` 语句对作为代码箱部分编译的文件也无任何影响。`mod` 关键字声明模组, Rust 会在与模组同名的文件中查找入该模组的代码。
# 本章小节
Rust 允许咱们将包拆分为多个代码箱,并代码箱拆分为模组,这样咱们可以一个模组引用另一模组中所定义的那些项目。通过指定绝对路径或相对路径,咱们就可以做到这点。使用 `use` 语句,这些路径就被带入作用域,这样咱们可以在该作用域中,对项目的多次引用使用一个更短的路径。模组代码默认是私有的,但咱们可通过添加 `pub` 关键字,将他们的定义构造为公开。
Rust 允许咱们将包拆分为多个代码箱,并拆分代码箱为模组,以便咱们可以一个模组引用定义在另一模组中的项目。咱们可通过指定绝对路径或相对路径做到这点。这些路径可在 `use` 语句带入作用域,以便咱们可以针对项目在该作用域中的多次引用,而使用较短的路径。默认情况下模组代码是私有的,但咱们可通过添加 `pub` 关键字,构造定义为公开。
在下一章中,我们将探讨标准库中的一些集合数据结构,在咱们良好组织的代码中,咱们就可以使用这些集合数据结构
在下一章中,我们将探讨标准库中的一些集合数据结构,咱们可在咱们良好组织的代码中使用他们
End