rust 入门-模块系统

166 阅读2分钟

rust 入门-模块系统

不太一样的模块系统

相信 rust 的初学者都会有这样一个疑问:我要怎么引入其他文件/文件夹下写好的函数变量等?。不同于 python 或者 java 这样通过文件路径来确定模块路径的语言,rust 有一套自己的模块系统。该模块系统的层级关系不一定就是文件的层级关系。

初探 mod

在 rust 中通过 mod 来定义一个模块,例如:

pub mod say {
    pub fn say_hello(){
        println!("hello");
    }
}

并且,如果我将其和 main 放在同一个目录:

├── src
│   ├── hello.rs
│   └── main.rs

那么此时我们应该通过以下方式引用 say_hello:

mod hello;
fn main() {
    hello::say::say_hello();
}

第一行 mod hello; 表示声明一个模块,rust 会认为以下文件路径为模块内容:

  • hello.rs
  • hello/mod.rs

而我们在 hello.rs 中又声明了新的模块 say,并且声明和定义在同一个地方。因此可以使用 hello::say::say_hello() 来访问, 还可以使用 use 语句:

mod hello;
use hello::say;
fn main() {
    say::say_hello();
}

可以看出,在 rust 中使用一个非第三方模块必须先使用 mod 声明,而不能直接使用 use

假设我们修改文件层级关系,将 say_hello 放入 src/hello/say.rs 中:

├── src
│   ├── hello
│   │   └── say.rs
│   └── main.rs

我们是否能使用 mod hello.say 来声明模块呢?答案是不能。我们必须在 hello 中建立 mod.rs 然后在 mod.rs 中声明。此时 3 个文件内容为:

// src/hello/say.rs
pub fn say_hello(){
    println!("hello");
}

// src/hello/mod.rs
pub mod say; // 声明 mod say

// src/main
mod hello;
fn main() {
    hello::say::say_hello();
}

此外,还有一种方法,我们可以声明与 hello 文件夹同名的 hello.rs,在 hello.rs 中可以访问 hello 文件夹下的代码文件:

├── src
│   ├── hello
│   │   └── say.rs
│   └── hello.rs
│   └── main.rs

此时代码为:

// src/hello/say.rs
pub fn say_hello(){
    println!("hello");
}

// src/hello.rs
pub mod say; // 声明 mod say

// src/main
mod hello;
fn main() {
    hello::say::say_hello();
}

这种方式不用在 hello 下建立一个 mod.rs

默认权限

在 rust 中默认权限都是外部不可访问,例如在 hello.rs 中定义一个 struct 然后在 main 中进行实例化,编译器会提示异常:

struct People{
    name: String
}

fn main() {
    let p = hello::People{
        name: String::from("dd")
    };
}

let p = hello::People{
  |                    ^^^^^^ private struct

试图给 People 定义添加 pub:

pub struct People{
    name: String
}

fn main() {
    let p = hello::People{
        name: String::from("dd")
    };
}

 |
4 |         name: String::from("dd")
  |         ^^^^^^^^^^^^^^^^^^^^^^^^ private field

又会收到新的异常,提示 name 这个字段是私有的。因此我们还需要:

pub mod say;

pub struct People{
    pub name: String
}

可以看出,rust 对权限管控非常严格,从 field 级别开始,如果不申明为 pub 外部一律无法访问。

总结

在 rust 中,模块有以下特点:

  1. 使用非第三方模块必须先使用 mod 进行定义后使用,不像其他语言可以直接 import。
  2. 声明语句 mod xxx; 表示从 xxx.rs 或 xxx/mod.rs 中寻找内容。
  3. 定义时默认为 private,如果要暴露给其他文件使用,必须显式声明为 pub