六、模块化
- 模块系统
- crate:一个模块的树形结构,它形成了库或二进制项目
- 包:Packages,cargo 的一个功能,允许你构建、测试和分享 crate
- 模块:允许你控制作用域和路径的私有性,可通过
use来使用公有的包 - 路径:一个命名,如结构体、函数、模块等项目的访问
1. crate 和 package
-
crate
- 一个模块的树形结构,它形成了库或二进制项目
- crate root 是一个源文件,Rust 编译的起点
-
包 (package)
- 提供一系列功能的一个或多个 crate
- 包含一个 Cargo.toml 文件
- 至多只能包含一个库
- 包含至少一个二进制 crate
-
Cargo 约定
- src/main.rs 就是一个与包同名的二进制 crate 的根节点
- 如果包目录中包含 src/lib.rs,则包带有与其同名的库 crate,且 src/lib.rs 是 crate 的根节点
2. Rust 模块
-
Rust 中,注册的一个
mod块即为一个模块 -
Rust 中,如果一个文件没有指定
mod块,则该文件的整个内容将被视为一个模块 (个人理解) -
特性
- 允许命名一个 item 的路径,并通过
use来引入一个指定的路径 - 允许使用
pub关键字来将 item 变为公有的
- 允许命名一个 item 的路径,并通过
-
Rust 中,默认所有的 item 都是私有的
- item 包括:函数、方法、结构体、枚举、(内部)模块、常量
-
作用
- 将一个 crate 的代码分组,提高代码的可读性与复用性
-
引用模块及其成员
- 使用关键字
use来引用 - 每一级的标识符之间,都以
::分割 - 相对路径
- 从当前模块开始,以
self开头,访问当前目录及其子目录和模块- 类似于 JavaScript 中的
./开头
- 类似于 JavaScript 中的
- 从当前模块开始,以
super开头,访问当前目录的父级目录及其子目录和模块- 类似于 JavaScript 中的
../开头
- 类似于 JavaScript 中的
- 从当前模块开始,以
- 绝对路径
- 从 crate 开始,以 crate 名或者字面值
crate开头,来访问对应的目录和模块- 类似于在 Typescript 中或有根目录别名解析的工具中,以
@/开头的访问
- 类似于在 Typescript 中或有根目录别名解析的工具中,以
- 从 crate 开始,以 crate 名或者字面值
- 使用关键字
-
模块的使用
-
使用
pub关键字暴露 item 的路径 -
使用
use关键字将 item 引入当前作用域 -
使用
as关键字将引入的 item 在当前作用域内重命名 -
使用
pub use重新导出 item -
在 Cargo.toml 文件的
[dependencies]项下列出需要使用的外部包和对应的版本,就可以像引入项目内的 item 一样引入这个包的 item 了 -
可通过嵌套路径消除大量相同路径的
use -
可通过 glob 运算符将某个模块内的所有 public 定义引入作用域
-
-
示例代码
-
src/main.rsmod structure; use structure::student; use student::Gender as StudentGender; use student::{check_number, create_student}; fn main() { student::struct_test(); let gender = StudentGender::Girl; let name = String::from("Ale"); let ale = create_student(name, 15, gender); ale.self_introduction(); let num = 1; println!("{} is {}", num, check_number(num)); let num2 = 0; println!("{} is {}", num2, check_number(num2)); } -
src/structure/mod.rspub mod student; -
src/structure/student.rspub enum Gender { Boy, Girl, } pub struct Student { age: u16, name: String, class: u8, grade: u8, gender: Gender, student_number: String, } impl Student { pub fn self_introduction(&self) { let gender = get_gender(&self.gender); println!("Hello everyone, my name is {}.", &self.name); println!("I'm a {} years old {}.", &self.age, gender); println!("I'm in class {}, grade {}.", &self.class, &self.grade); println!("My student number is {}.", &self.student_number); println!("I'm very happy to join this big family!"); println!(); } } pub fn struct_test() { let jelly = create_student(String::from("Jelly"), 15, Gender::Girl); jelly.self_introduction(); let cherry = Student { name: String::from("Cherry"), student_number: get_student_number(), gender: Gender::Boy, ..jelly }; cherry.self_introduction(); } pub fn create_student(name: String, age: u16, gender: Gender) -> Student { return Student { age, name, gender, class: 12, grade: 8, student_number: get_student_number(), }; } fn get_student_number() -> String { return String::from("abc"); } fn get_gender(gender: &Gender) -> String { match gender { Gender::Boy => String::from("boy"), Gender::Girl => String::from("girl"), } }
-