模块
以mod关键字开头来定义一个模块。例如:
mod front_of_house {
}并且在模块内部可以继续定义其它模块:
mod front_of_house {
mod housting{
}
mod serving {
}
}在项目管理中就提到过crate是一个树形模块结构,而src/main.rs和src/lib.rs正是各自树形结构的根节点。
所有的模块树都处于一个名为crate的隐式根模块下:
crate
|
|--- front_of_house
|
|---hosting
|
|---serving通过模块将相同相关的定义分到一组,使得代码的结构清晰易于管理。在模块的内部还可以包含其它条目的定义,如结构体、枚举、trait、函数等。
要想在模块树中找到某个条目,需要使用路径
路径
路径的形式有两种:
- 以crate包名或者
crate字面量从根节点开始的绝对路径。 - 使用
self、super或内部标识符从当前模块开始的相对路径。self::可以不写,默认表示当前模块;super表示父模块。
使用::分割标识符。
一个调用模块函数的例子如下,但是无法通过编译:
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
}
}
fn fn eat_at_restaurant() {
// 通过绝对路径调用函数
crate::front_of_house::hosting::add_to_waitlist();
//通过相对路径调用函数
front_of_house::hosting::add_to_waitlist();
}使用相对路径,移动代码的时候需要保证相对位置不变才能保持有效;使用绝对路径,可以不需要保证相对位置,但是需要修改绝对路径。 因为开发中往往会独立移动代码,所以更倾向于使用绝对路径。
私有边界
上一节中的示例代码无法通过编译,这是因为虽然路径正确但是缺少访问私有域的边界。
模块定义了Rust中的私有边界。Rust中的所有条目(函数、方法、结构体、枚举、模块、常量)默认都是私有的。
父级模块无法使用子模块中的私有条目,子模块可以使用它所有祖先模块中的条目。这样可以隐藏内部的实现细节。
在模块前添加pub关键字可以公开这个模块,但是公开模块并不会影响其内部条目的状态。仅仅代表着祖先模块有权限指向此模块。
要想使用一个模块内的一个函数,那么这个模块和这个函数都要是pub公开的。
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
fn fn eat_at_restaurant() {
// 通过绝对路径调用函数
crate::front_of_house::hosting::add_to_waitlist();
//通过相对路径调用函数
front_of_house::hosting::add_to_waitlist();
}注意上面代码,front_of_house这个模块并没有公开,但是父模块是可以指向子模块的,但是没有权限访问其内部内容。
使用super从父模块开始
fn serve_order() {
}
mod back_of_house {
fn fix_incorrect_order() {
cook_order();
super::serve_order();
}
fn cook_order() {
}
}将结构体和枚举声明为公共的
结构体和枚举都可以使用pub声明为公共的
结构体公开但是内部的字段仍然默认是私有的,需要逐一决定是否公开。如果公开结构体内包含私有字段,那么一般需要提供一个New方法,不然其它模块无法创建这个结构体对象。
而枚举公开的话,它的所有变体自动变为了公共状态。因为枚举在所有变体都公共可用才能实现最大的功效。
每次都通过路径来调用会显得很麻烦,为了简单起见可以使用use 关键字来将路径导入作用域中,在作用域中就可以很简写路径了。
tags: 项目管理