Updated src/packages_crates_and_modules/defining_modules.md'.

This commit is contained in:
Hector PENG
2026-03-14 19:16:39 +08:00
parent 700b5a62b0
commit c0d04fe3f7
11 changed files with 61 additions and 85 deletions

View File

@@ -1,8 +1,6 @@
[package]
name = "backyard"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
edition = "2024"
[dependencies]

View File

@@ -4,5 +4,5 @@ pub mod garden;
fn main() {
let plant = Asparagus {};
println! ("I'm growing {:?}!", plant);
println! ("I'm growing {plant:?}!");
}

View File

@@ -1,8 +0,0 @@
[package]
name = "restaurant"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

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

View File

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

View File

@@ -1,28 +0,0 @@
mod back_of_house {
pub enum Appetizer {
Soup,
Salad,
}
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"),
}
}
}
}
mod front_of_house;
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}

View File

@@ -0,0 +1,6 @@
[package]
name = "restuarant"
version = "0.1.0"
edition = "2024"
[dependencies]

View File

@@ -0,0 +1,15 @@
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
fn seat_at_table() {}
}
mod serving {
fn take_order() {}
fn serve_order() {}
fn take_payment() {}
}
}

View File

@@ -40,7 +40,7 @@
- [包、代码箱与模组](Ch07_Managing_Growing_Projects_with_Packages_Crates_and_Modules.md)
- [代码包与代码箱](packages_crates_and_modules/packages_and_crates.md)
- [定义用于控制作用域及隐私性的模组](packages_crates_and_modules/defining_modules.md)
- [在模组下控制作用域及隐私](packages_crates_and_modules/defining_modules.md)
- [引用模组树中某个项目的路径](packages_crates_and_modules/paths.md)
- [使用 `use` 关键字将路径带入作用域](packages_crates_and_modules/the_use_keyword.md)
- [将模组分成不同文件](packages_crates_and_modules/separating_modules.md)

View File

@@ -1,39 +1,37 @@
# 定义控制作用域隐私的模组
# 在模组下控制作用域隐私
**Defining Modules to Control Scope and Privacy**
在这一小节中,我们将讨论模组和模组系统的其他部分,即
- *路径path*,他允许咱们给项目命名;
- 将路径带入作用域的 `use` 关键字;
- 以及将项目构造为公开的 `pub` 关键字等。
在本节中,我们将讨论模组和模组系统的其他部分,即允许咱们给项目取名的 *路径paths*、将路径引入作用域的 `use` 关键字,以及将项目构造为公开的 `pub` 关键字等。我们还将讨论 `as` 关键字、外部包 `glob` 操作符。
首先,我们将以一份方便咱们今后组织咱们代码的规则清单开始。然后,我们将详细解释每一条规则。
我们还将讨论 `as` 关键字、外部包 `glob` 操作符。
## 模组速查表
**Modules Cheat Sheet**
在深入模组与路径的细节前,我们在此提供一个快速参考,有关模组、路径、`use` 关键字及 `pub` 关键字在编译器中的工作原理,以及大多数开发人员组织他们的代码的方式。尽管我们将在这一章中逐一讲解这些规则的示例,但这里也是回顾模组工作原理的绝佳之处。
- **从代码箱根开始**:编译代码箱时,编译器首先在代码箱根文件(通常是库代码箱的 `src/lib.rs`及二进制代码箱的 `src/main.rs`)中查找要编译的代码;
这里我们提供了有关模组、路径、`use` 关键字和 `pub` 关键字,在编译器中如何运作,以及大多数开发人员如何组织代码的快速参考。我们将在本章节中,逐个讨论这些规则的示例,但这是个很到的,作为模组工作原理的提醒的地方。
+ **声明模组**:在代码箱根文件中,咱们可声明新的模组;假设咱们以 `mod garden;` 声明了个 ”花园“ 模组。编译器将在以下位置查找该模组的代码:
- 内联式,在花括号内,其替换 `mod garden` 后分号;
- 在文件 `src/garden.rs` 中;
- 在文件 `src/garden/mod.rs` 中。
- **从代码箱根开始**:编译代码箱时,编译器首先会在代码箱根文件(通常是库代码箱的 `src/lib.rs`,或二进制代码箱的 `src/main.rs`)中,查找要编译的代码
+ **声明模组**:在代码箱根文件中,咱们可以声明出新的模组;比如,咱们以 `mod garden;`,声明一个 ”花园“ 模组。编译器将在下面这些地方,查找该模组的代码:
- 内联式,在替换 `mod garden` 后分号的花括号内;
- 文件 `src/garden.rs` 中;
- 文件 `src/garden/mod.rs` 中。
+ **声明子模组**:在除代码箱根外的任何文件中,都可以声明子模组。例如,咱们可能会在 `src/garden.rs` 中,声明 `mod vegetables;`。编译器将在下面这些地方的父模组目录中,查找该子模组的代码:
+ **声明子模组**:在除代码箱根外的任何文件中,咱们都可以声明子模组。例如,咱们可在 `src/garden.rs` 中声明 `mod vegetables;`。编译器将在以下位置的命名为父模组的目录下,查找该子模组的代码
- 内联式,直接跟在 `mod vegetables` 之后,代替分号的花括号内;
- 文件 `src/garden/vegetables.rs` 中;
- 文件 `src/garden/vegetables/mod.rs` 中。
- 文件 `src/garden/vegetables.rs` 中;
- 文件 `src/garden/vegetables/mod.rs` 中。
- **模组中代码的路径**:一旦某个模组成为咱们代码箱的一部分,只要隐私规则允许,咱们就可以同一代码箱的任何其他地方,使用代码的路径来引用该模组中的代码。例如,花园蔬菜模组中的 `Asparagus` (芦笋)类型,就可以在 `crate::garden::vegetables::Asparagus` 处找到。
- **模组中代码的路径**:一旦模组成为咱们代码箱的一部分,只要隐私规则允许,咱们就可以使用到代码的路径,从同一代码箱的任何其他地方引用该模组中的代码。例如,花园蔬菜模组中的 `Asparagus` (芦笋)类型,将于 `crate::garden::vegetables::Asparagus` 处找到。
- **私有与公开**:模组内的代码默认对其父模组私有的。要将某个模组构造为公开,可使用 `pub mod` 代替 `mod` 声明该模组。要将某个公开模组中的项目也构造为公开,请在其声明前使用 `pub`
- **私有与公开**默认情况下,模组内的代码对其父模组属于私有的。要构造模组为公开,就要以 `pub mod` 而不是 `mod` 声明。要将公开模组中的项目也构造为公开,就要在他们的声明前使用 `pub`
- **`use` 关键字**:在作用域`use` 关键字创建出到项目的快捷方式以减少长路径的重复。在任何可以引用 `crate::garden::vegetables::Asparagus` 的作用域中,咱们都可以使用 `use crate::garden::vegetables::Asparagus;` 创建出一个快捷方式,并在那以后,咱们就只需写下 `Asparagus`,就可以在该作用域中使用这个类型。
- **`use` 关键字**:在某一作用域`use` 关键字创建项目的快捷方式以减少长路径的重复。在任何可以引用 `crate::garden::vegetables::Asparagus` 的作用域中,咱们都可以 `use crate::garden::vegetables::Asparagus;` 创建快捷方式,那以后,咱们就只需写下 `Asparagus` 即可在这一作用域中使用类型。
,我们创建一个说明这些规则的名为 `backyard` 的二进制代码箱。这个代码箱的目录也称`backyard`其中包含下面这些文件目录:
这里,我们创建一个名为 `backyard` 的二进制代码箱说明这些规则。这个代码箱的目录同样名`backyard`包含以下这些文件目录:
```console
@@ -48,7 +46,7 @@ backyard
```
本例中的代码箱根文件 `src/main.rs`,他包含:
这一情形下,代码箱根文件 `src/main.rs`,他包含:
文件名:`src/main.rs`
@@ -64,8 +62,7 @@ fn main() {
}
```
`pub mod garden;` 这行告诉编译器,要包含其在 `src/garden.rs` 中找到的代码,即:
其中 `pub mod garden;` 行告诉编译器,要包含其在 `src/garden.rs` 中找到的代码,即:
文件名:`src/garden.rs`
@@ -75,7 +72,7 @@ pub mod vegetables;
```
在这里,`pub mod vegetables;` 表示也包含了 `src/garden/vegetables.rs` 中的代码。这些代码是:
在这里,`pub mod vegetables;` 表示 `src/garden/vegetables.rs` 中的代码也会包含。该代码是:
```rust
@@ -83,22 +80,18 @@ pub mod vegetables;
pub struct Asparagus {}
```
现在就来进入到这些规则的细节,并在实际操作中对他们进行演示吧!
现在我们来深入这些规则的细节并在操作中演示他们!
## 把有关联的代码分组在模组中
## 以模组组织相关代码
**Grouping Related Code in Modules**
所谓 *模组module*,让我们可以组织代码箱内的代码,出于可读性及重用目的。模组还允许我们控制程序项目(译注:变量、类型及函数等)的 *隐私*,因为模组内的代码默认是私有的。私有项目属于内部的实现细节,对外部使用不可用。我们可选择构造模组及其内项目公开,这会暴露他们以允许外部代码使用并依赖他们。
举个例子,我们来编写一个库代码箱,提供餐厅功能。我们将定义函数的签名,但将他们的主体留空,以专注于代码的组织而不是餐厅的实现。
*模组modules* 让我们可以把代码组织在代码箱中,以提高可读性并方便重复使用。模组还允许我们控制程序项目的私密性,因为某个模组内的代码默认为私有。私有项目是一些内部的实现细节,不供外部使用。我们可以选择将模组及其中的项目公开,这样就可以让外部代码使用和依赖他们
在餐饮业餐厅的一些部分称为前厅front of house其他部分称为后厨back of house。*前厅* 是顾客所在的地方;包括餐厅领台为顾客安排座位、服务员接受点单和付款,以及调酒师调制饮料的地方。*后厨* 是厨师和厨工在厨房工作、洗碗工清洁以及经理进行行政工作的地方
例如,我们来编写一个提供餐厅功能的库代码箱。我们将定义函数签名,但函数体留空,以专注于代码的组织,而不是实现餐厅的实现
在餐饮业,餐厅的一些部分被称为 *前厅front of house*,其他部分被称为 *后厨back of house*。前厅是顾客所在的地方;包括餐厅领台为顾客安排座位、服务员接受点单和付款,以及调酒师调制饮料的地方。后厨是厨师和厨工在厨房工作、洗碗工进行清洁和经理进行行政工作的地方。
为了以这种方式架构我们的代码箱,我们可以将其函数,组织成一些嵌套的模组。请运行 `cargo new restaurant --lib`,创建一个名为 `restaurant` 的新库;然后在 `src/lib.rs` 中,输入下面清单 7-1 中的代码,定义一些模组和函数签名。下面是前台部分:
为了以这种方式架构我们的代码箱,我们可将其功能组织成嵌套的模组。请通过运行 `cargo new restaurant --lib` 创建一个名为 `restaurant` 的新库;然后输入下面清单 7-1 中的代码到 `src/lib.rs` 中,定义一些模组与函数签名。这段代码属于前台部分
文件名:`src/lib.rs`
@@ -121,16 +114,17 @@ mod front_of_house {
}
```
*清单 7-1包含着其他包含了函数模组的 `front_of_house` 模组*
<a name="listing_7-1"></a>
**清单 7-1**`front_of_house` 模组包含其他模组,而其他模组包含函数
我们使用后跟模组名字(本例中为 `front_of_house`)的 `mod` 关键字定义个模组。随后模组的主体位于花括号内。在模组内部,我们可以放置其他模组,就像本例中 `hosting``serving` 模组。模组还可以包含其他项目的定义,如结构体、枚举、常量、特质,以及如同清单 7-1 中的函数。
我们后跟模组名字(在这一情形下,即 `front_of_house`)的 `mod` 关键字定义个模组。模组的主体随后位于花括号内。在模组内部,我们可以放置其他模组,就像本例中 `hosting``serving` 模组。模组还可以容纳其他程序项目的定义,如结构体、枚举、常量、特质,以及清单 7-1 中的函数
经由模组的使用,就可以将有关联的一些定义组织在一起,并以他们因何相关而取个名字。使用代码的程序员们,就可以根据这些分组,而非通读全部的这些定义,来浏览代码,那么在找到他们想要使用的那些定义时,就会容易一些。而对于要往该代码增加新功能的那些程序员,就清楚在哪里放置代码,来保持程序组织有序。
通过使用模组,我们可将相关定义组织在一起并表明他们相关的原因。使用这段代码的程序员可以根据分组浏览代码,而不必通读所有定义,从而更容易找到他们攸关的定义。往这段代码增加新功能的程序员将清楚要将代码放在何处以保持程序组织有序。
前面我们曾提到`src/main.rs` `src/lib.rs` 称为代码箱根。之所以叫这两个文件为代码箱根,是因为这两个文件的内容构成了位于该代码箱结构(即 *模组树module tree*)根部,名为 `crate` 的模组。
早先我们曾提到 `src/main.rs` `src/lib.rs` 称为代码箱根。他们名字的原因是这两个文件的内容构成了代码箱模组结构,称为 *模组树module tree* 根处名为 `crate` 的模组。
清单 7-2 示了清单 7-1 中结构的模组树。
清单 7-2 示了清单 7-1 中结构的模组树。
```console
crate
@@ -144,7 +138,8 @@ crate
└── take_payment
```
*清单 7-2清单 7-1 中代码的模组树*
<a name="listing_7-2"></a>
**清单 7-2**:清单 7-1 中代码的模组树
该树显示了其中一些模组是如何嵌套在另一模组中的;例如,`hosting` 嵌套在 `front_of_house` 中。该树还显示其中一些模组彼此属于 *同辈siblings*,即他们被定义在同一模组中;`hosting``serving``front_of_house` 中定义的同辈份模组。如果模组 A 包含在模组 B 中,我们就说模组 A 是模组 B 的子模组,而模组 B 是模组 A 的父模组。请注意,整个模组树的根,都位于名为 `crate` 的隐式模组下。

View File

@@ -30,7 +30,7 @@ main.rs
在我们运行 `cargo new` 后,我们使用 `ls` 来查看 Cargo 创建了什么。在 `my-project` 目录下,有个 `Cargo.toml` 文件,给到我们一个包。还有个包含 `main.rs``src` 目录。请以咱们的文本编辑器打开 `Cargo.toml`,注意其中没有提到 `src/main.rs`。Cargo 遵循一项约定,即 `src/main.rs` 是与包同名的二进制代码箱的代码箱根。同样Cargo 知道当包目录包含 `src/lib.rs` 时,那么该包就包含一个与包同名的库代码箱,并且 `src/lib.rs` 即为其代码箱根。Cargo 会传递代码箱根文件给 `rustc` 以构建库或二进制程序。
在这里,我们有个仅包含 `src/main.rs` 的包,这意味着他仅包含一个名为 `my-project` 的二进制代码箱。当某个包包含 `src/main.rs``src/lib.rs` 时,那么他就有两个代码箱:一个二进制代码箱和一个库代码箱,二者均有着与包相同的名字。通过放置文件 `src/bin` 目录下,一个包可以有着多个二进制代码箱:每个文件都将是个单独的二进制代码箱。
在这里,我们有个仅包含 `src/main.rs` 的包,这意味着他仅包含一个名为 `my-project` 的二进制代码箱。当某个包包含 `src/main.rs``src/lib.rs` 时,那么他就有两个代码箱:一个二进制代码箱和一个库代码箱,二者均有着与包相同的名字。通过放置文件 `src/bin` 目录下,一个包可以有着多个二进制代码箱:每个文件都将是个单独的二进制代码箱。
End