Rust通过包和模块来组织所有的代码,其中每一个Rust项目都是一个包。平时所说的实现给中功能的第三方库每一个都是一个包,这些库都是以一个包的形式发布。
包
一个Rust项目可以依赖其他的包,这只需要在 Cargo.toml
的 [dependencies]
中列出即可。所有在 Cargo.toml
中列出的被依赖包,都可以需要使用它们的代码文件中使用 extern crate
声明使用。
例如有以下依赖:
[dependencies]
# 这里没有书写任何被依赖库的版本,*代表使用最新版本
image = "*"
那么在 main.rs
文件的开头就需要这样来引用。
extern crate image;
模块
模块是Rust中代码的命名空间,是函数、类型、结构体等代码的容器。包解决的是Rust项目间代码共享的问题,而模块解决的是项目内部代码组织的问题。模块可以嵌套,一个模块拥有一系列的子模块是非常常见的。
如果把所有的模块都书写在一个文件中,那么可以采用以下形式。
mod master_module {
pub mod sub_module_1 {
// 这个子模块是公共的,可以被其他的模块访问到
...
}
mod sub_module_2 {
// 这个子模块是私有的,从其他的模块是无法访问到的
...
}
}
模块中的内容默认都是私有的,只有添加了
pub
关键字以后,才会变为公共的,可以被外部访问到。
如果需要把模块定义在独立的文件或者文件夹中,那么就需要使用模块的声明语法了。假设有以下项目结构。
在这个项目中, direct.rs
是一个存在于独立文件的模块,目录 composite
是一个存在与独立文件夹的模块,所以这两个模块都需要在 main.rs
中声明。在 main.rs
文件的开头就可以如下一样声明。
pub mod direct;
pub mod composite;
这样一来,如果在 main.rs
同目录下,如果存在 direct.rs
,Rust就会把 direct.rs
作为一个模块来对待,并且在 direct.rs
文件中不必再使用 mod
关键字声明模块了。对于目录 composite
,Rust会首先去寻找其中的 mod.rs
文件,这个文件是使用目录作为模块的统领文件,其下的所有子模块也都是在这个 mod.rs
文件中定义。
模块 composite
下的子模块需要在 mod.rs
文件中定义,其中内容如以下示例所示。
pub mod analysis;
pub mod statistics;
mod.rs
文件中除了可以包含子模块的定义以外,要包含的还有当前模块中需要定义的功能内容。
内容导入
在任何时候,都可以使用操作符 ::
采用绝对路径的方式访问模块中的内容,例如从 main.rs
访问 analysis.rs
中定义的内容就如同下面这样。
::composite::analysis::AnalysisDefinedContent
这些书写较为繁琐,所以可以提前使用 use
关键字将要使用的内容导入。导入会让被导入的内容成为当前模块中的一个局部别名。 use
关键字会自动转换根路径,所以不需要使用最前导的 ::
操作符。例如导入上例的内容,格式就如下所示。
use composite::analysis::AnalysisDefinedContent;
// 还可以一次性导入多个内容
use composite::analysis::{AnalysisDefinedContent, AnotherUseableContent};
// 或者直接导入全部内容
use composite::analysis::*;
// 导入一个模块
use composite::analysis;
使用 use
导入模块中的内容不仅可以导入具体内容,还可以导入一个模块,这样模块中可访问的内容就可以使用 module::content
的格式来访问了。
模块不会从其父模块继承名字,子模块也看不到父模块中定义的内容,即便这些内容都是公共的。如果要在子模块中使用父模块中定义的内容,需要使用以下声明明确导入父模块声明的内容。
use super::ParentDefinedContent;
然而父模块要访问子模块中定义的内容,也同样需要明确导入。
use self::ChildModule::ChildDefinedContent;