Rust 模块

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()

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战