Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

7.6 将模块拆分为不同文件

7.6.1. 将模块的内容移动到其他文件

如果在模块定义时模块名后边跟的是;而不是代码块,Rust就会在src目录下找与模块同名的.rs文件加载其中的内容。无论模块的内容是在同一个文件里面还是在不同的文件里面,模块树的结构都不会发生变化。

来看一个例子(lib.rs):

#![allow(unused)]
fn main() {
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() { }
    }
}

pub use crate::front_of_house::hosting::add_to_waitlist;

pub fn eat_at_restaurant() {
    add_to_waitlist();
}
}

这样写就是把所有模块放在同一个文件里。如果要把它放在不同的文件里,就要这么写:

Step 1:新建文件

假如要把front_of_house分出去,就需要在src目录下创建同名的.rs文件: 文件资源管理器显示在 src 下新建的 front_of_house.rs

Step 2:剪切代码

把原本在front_of_house下的代码从原位置剪切到这个front_of_house.rs这个文件里,也就是把这一段剪切走:

#![allow(unused)]
fn main() {
pub mod hosting {
    pub fn add_to_waitlist() { }
}
}

编辑器显示已粘贴到 front_of_house.rs 的 hosting 模块代码

Step 3:修改原处

打开front_of_house原来定义的地方(lib.rs)。这个时候就不用后面的代码块了,把它连着{}都删去,加上;即可(其它的无关代码不要动),原本代码是(lib.rs):

#![allow(unused)]
fn main() {
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() { }
    }
}

pub use crate::front_of_house::hosting::add_to_waitlist;

pub fn eat_at_restaurant() {
    add_to_waitlist();
}
}

改成(lib.rs):

#![allow(unused)]
fn main() {
mod front_of_house;

pub use crate::front_of_house::hosting::add_to_waitlist;

pub fn eat_at_restaurant() {
    add_to_waitlist();
}
}

lib.rs 中用分号声明 mod front_of_house,旁侧为 front_of_house.rs 内容

7.6.2. 子模块的拆分

如果front_of_house下面有很多模块怎么办?这时就需要把这些子模块放到不同的文件里,以便更好地组织代码。但该怎么做呢?像刚才那样,把所有子模块都放在src目录下吗?那样src里文件会太多,而且模块之间的层级关系也体现不出来。

Rust给出了一个不错的方案:把所有子模块文件放在以父模块命名的文件夹里。具体来说,需要先创建一个与父模块同名的文件夹,然后在该文件夹内用.rs文件来存放子模块或条目。

举个例子,如果我要把hosting独立出去成一个单独的文件,操作不仅仅是在src下创建一个同名.rs文件,而是需要先新建一个父模块的同名文件夹,在这个例子中父模块的名字是front_of_house,所以就要创建名字为front_of_house的文件夹。

然后再在这个文件夹下创建与条目名/模块名相同的.rs文件,在这个例子中是要把hosting独立出去,所以这个文件应该叫做hosting.rs文件资源管理器显示 front_of_house 文件夹及其下的 hosting.rs

hosting.rs里存储hosting的内容,也就是:

#![allow(unused)]
fn main() {
pub fn add_to_waitlist() { }
}

现在可以像之前处理lib.rs那样,把front_of_house.rshosting模块的代码块连同{}删掉,并加上;。把它从(front_of_house.rs):

#![allow(unused)]
fn main() {
pub mod hosting {
    pub fn add_to_waitlist() { }
}
}

改成简单的:

#![allow(unused)]
fn main() {
pub mod hosting;
}

分栏编辑器显示 lib.rs、声明 hosting 的 front_of_house.rs 与 hosting.rs

Rust也支持以module_name/mod.rs的形式拆分模块。所有模块内容都存放在mod.rs中,文件夹名即表示模块名。这种方式在Rust中仍然完全受支持,但在现代Rust代码中,它通常更像是旧式模块布局的延续,而不是默认偏好。

如果用这种方式拆分模块,看起来会是这样: 使用 front_of_house/mod.rs 与 hosting/mod.rs 的模块布局

7.6.3. 拆分的优点

随着模块变大,该技术让程序员可以把模块的内容移动到其他文件中。