Rust 模块有助于将程序划分为逻辑单元,以提高可读性和组织性。
一旦程序变得更大,将其拆分为多个文件或命名空间就变得很重要。模块有助于构建我们的程序。
模块是项目的一个集合:函数、结构体,甚至其他模块。
在 Rust 中定义模块
mod
关键字用于定义模块。模块的语法是
// syntax of a module
mod module_name {
// code
}
这里,module_name
是模块的名称。
现在,让我们定义一个模块。
// a module named config
mod config {
// a function print inside of the module
fn print() {
println!("config!");
}
}
在上面的示例中,我们使用 mod
关键字创建了一个名为 config
的模块。
在模块内部,我们可以定义多个项。在这里,我们定义了 print()
函数。
Rust 模块内项的可见性
模块内的项可以是私有的或公有的。默认情况下,模块是私有的。这意味着模块内的项无法在模块外部访问。
pub
关键字可用于为项提供公共可见性。
让我们看一个例子。
mod config {
// items in modules by default have private visibility
fn select() {
println!("called config::select");
}
// use the `pub` keyword to override private visibility
pub fn print() {
println!("called config::print");
}
}
在这里,我们定义了一个名为 config
的模块,其中包含两个函数 select()
和 print()
。
print()
函数以 pub
关键字开头,这意味着它具有公共可见性。但是,select()
函数没有。
如果我们编译上面的程序,我们不会得到任何输出,因为我们还没有使用这些函数。
warning: function `select` is never used --> src/lib.rs:3:8 | 3 | fn select() { | ^^^^^^ | = note: `#[warn(dead_code)]` on by default warning: function `print` is never used --> src/lib.rs:8:12 | 8 | pub fn print() { | ^^^^^
现在,让我们调用模块内的函数。
mod config {
// items in modules by default have private visibility
fn select() {
println!("called config::select");
}
// use the `pub` keyword to override private visibility
pub fn print() {
println!("called config::print");
}
}
fn main() {
// public items inside module can be accessed outside the parent module
// call public print function from display module
config::print();
}
输出
called display::print
在这里,我们使用 config::print()
的语法调用 config
模块内的公共函数 print()
。::
运算符用于分隔模块名称和要在模块内调用的项。
然而,模块内的私有项在模块外部是无法访问的。如果我们调用 config
模块内的私有函数 select()
,我们会得到一个编译错误。
mod config {
// items in modules by default have private visibility
fn select() {
println!("called config::select");
}
// use the `pub` keyword to override private visibility
pub fn print() {
println!("called config::print");
}
}
fn main() {
// private items inside module cannot be accessed outside the parent module
// calling private select function inside config module will cause a compilation error
display::select();
}
错误
error[E0603]: function `select` is private --> src/main.rs:16:14 | 16 | display::select(); | ^^^^^^ private function
错误提到“函数 `select` 是私有的”。因此,模块内项的可见性是一个重要的设计考虑因素。
注意: 当与 pub
关键字一起使用时,模块也可以具有公共可见性。
示例:在 Rust 中使用模块
mod player {
// private function
fn focus() {
println!("called player::focus");
}
// public function
pub fn shift() {
println!("called player::shift");
}
// public function
pub fn jump() {
// call private function focus and shift inside the module
focus();
shift();
println!("called player::jump");
}
}
fn main() {
// call public function jump from player module
player::jump();
}
输出
called player::focus called player::shift called player::jump
在这里,我们在 player
模块中定义了多个函数。请注意,我们能够在同一模块内的另一个函数 jump()
中调用私有函数 focus()
。
嵌套模块
一个模块可以定义在另一个模块内部。这称为模块嵌套。
让我们看一个例子。
// nested module
pub mod player {
pub mod sprite {
pub fn create() {
println!("called player::sprite::create");
}
}
}
fn main() {
// call public function create from sprite module which is inside player module
player::sprite::create();
}
输出
called player::sprite::create
在这里,我们在 player
模块内嵌套了一个 sprite
模块。
我们在 sprite
模块内定义了一个公共函数 create()
,该函数在 main()
函数的模块外部使用 player::sprite::create()
调用。
Rust 中的 `use` 关键字
我们可以使用 use
关键字将模块内的项引入当前作用域。use
关键字帮助我们避免编写完整的模块路径来调用函数。
让我们使用 use
关键字重写我们的嵌套模块示例。
// nested module
pub mod player {
pub mod sprite {
pub fn create() {
println!("called player::sprite::create");
}
}
}
// bring the create function into scope
use player::sprite::create;
fn main() {
// call public function directly
create();
}
输出
called player::sprite::create
在这里,我们使用 use
关键字将 create()
函数从位于 player
模块内的 sprite
模块引入当前作用域。这使我们可以直接调用 create()
函数,而无需使用完整的限定名称 player::sprite::create()
。