为了向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 errorsFor 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.08sD:\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正文。