为了向 Rust 展现在模块树中找到我的项目的地位,咱们应用的门路与浏览文件系统时应用的门路雷同。如果要调用函数,则须要晓得其门路。
门路能够采纳两种模式:
绝对路径从板条箱根开始通过应用一个 create 名称或一个文字 create。
相对路径从以后模块开始,并在以后模块中应用 self,super 或标识符。
绝对路径和相对路径后跟一个或多个标识符,并用双冒号分隔(::)
例如:
mod front_of_house {
mod hosting {fn add_to_waitlist() {}}
}
pub fn eat_at_restaurant() {
// 绝对路径
crate::front_of_house::hosting::add_to_waitlist();
// 相对路径
front_of_house::hosting::add_to_waitlist();}
运行 cargo build
会报错:
D:\learn\cargo_learn>cargo build
Compiling cargo_learn v0.1.0 (D:\learn\cargo_learn)
error[E0603]: module `hosting` is private
--> src\lib.rs:9:28
|
9 | crate::front_of_house::hosting::add_to_waitlist();
| ^^^^^^^ private module
|
note: the module `hosting` is defined here
--> src\lib.rs:2:5
|
2 | mod hosting {
| ^^^^^^^^^^^
error[E0603]: module `hosting` is private
--> src\lib.rs:12:21
|
12 | front_of_house::hosting::add_to_waitlist();
| ^^^^^^^ private module
|
note: the module `hosting` is defined here
--> src\lib.rs:2:5
|
2 | mod hosting {
| ^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0603`.
error: could not compile `cargo_learn`.
To learn more, run the command again with --verbose.
谬误音讯表明模块托管是公有的。换句话说,咱们领有托管模块和 add_to_waitlist 函数的正确门路,但 Rust 无法访问它们,因为它无法访问公有局部。
模块不仅仅对组织代码有用。它们还定义了 Rust 的隐衷边界:封装实现细节的行不容许内部代码晓得,调用或依赖。因而,如果要将我的项目设为函数或构造公有,则将其放在模块中。
Rust 中隐衷的工作形式是默认状况下所有我的项目(函数,办法,构造,枚举,模块和常量)都是公有的。父模块中的我的项目不能应用子模块中的公有我的项目,然而子模块中的我的项目能够应用其先人模块中的我的项目。起因是子模块包装并暗藏了其实现详细信息,然而子模块能够看到定义它们的上下文。要持续应用餐厅的隐喻,能够将隐衷规定视为餐厅的后盾办公室:餐厅客户的隐衷是私人的,但办公室经理能够查看并在其经营的餐厅中做任何事件。
Rust 抉择以这种形式使模块零碎起作用,以便默认暗藏外部实现细节。这样,您就晓得能够更改外部代码的哪些局部而不会毁坏内部代码。然而,您能够应用 pub 关键字将我的项目公开,从而将子模块代码的外部局部公开给内部先人模块。
因而咱们须要将应用到的 paths 裸露进去,通过应用关键字pub
:
mod front_of_house {
pub mod hosting {pub fn add_to_waitlist() {}}
}
pub fn eat_at_restaurant() {
// 绝对路径
crate::front_of_house::hosting::add_to_waitlist();
// 相对路径
front_of_house::hosting::add_to_waitlist();}
运行:cargo build
D:\learn\cargo_learn>cargo build
Finished dev [unoptimized + debuginfo] target(s) in 0.08s
D:\learn\cargo_learn>
通过 super
实现相对路径
在 rust 中 mod 中的函数通过应用 super::
拜访与上一级同级别的 paths:
fn serve_order() {}
mod back_of_house {fn fix_incorrect_order() {cook_order();
super::serve_order();}
fn cook_order() {}
}
fn main() {}
公开构造和枚举
咱们还能够应用 pub 将构造和枚举指定为公共,但还有一些其余细节。如果咱们在构造定义之前应用 pub,则将构造公开,但构造的字段仍将是公有的。咱们能够依据状况将每个字段公开或不公开。在下例中,咱们定义了一个公共的 back_of_house :: Breakfast 构造,其中蕴含一个公共的 toast 字段,但一个公有的 season_fruit 字段。这样能够在一家餐厅中模仿状况,客户能够在这家餐厅抉择餐点附带的面包类型,然而厨师会依据节令和库存来决定餐点中搭配哪种水果。可用的水果变动很快,因而客户无奈抉择水果,甚至看不到他们会失去哪种水果。
#![allow(unused_variables)]
fn main() {
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() {
// 通过 summer 订购黑麦面包早餐
let mut meal = back_of_house::Breakfast::summer("Rye");
// 扭转主见,想吃什么面包
meal.toast = String::from("Wheat");
println!("我喜爱 {} 吐司,谢谢", meal.toast);
// 如果咱们勾销正文,则下一行将不会编译;咱们不容许查看或批改 seasonal_fruit
// meal.seasonal_fruit = String::from("blueberries");
}
}
与之不同的是,如果咱们将一个枚举公开,则其所有变体都将公开。咱们只须要 pub 在 enum 关键字之前,如下所示:
#![allow(unused_variables)]
fn main() {
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;
}
}
因为咱们公开了 Appetizer 枚举,所以咱们能够在 eat_at_restaurant 中应用 Soup 和 Salad 变体。枚举不是很有用,除非它们的变体是公开的。在每种状况下都必须用 pub 正文所有枚举变量会很烦人,因而枚举变量的默认设置是公开的。构造通常在不公开其字段的状况下很有用,因而,构造字段遵循通常所有内容都默认为公有的个别规定,除非应用 pub 正文。