为了向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正文。