返回介绍

9.3 模块

发布于 2024-10-13 11:25:31 字数 3433 浏览 0 评论 0 收藏 0

模块 (module)是命名空间(namespace),是函数、类型、常量的容器,用来组织和隔离代码。模块可以是一个目录,一个源文件,或在单个文件内嵌套。

  • 根文件(main.rs, lib.rs)模块名为 crate
  • 各级文件以 crate 为起点,构成模块树。
  • 子模块,用于分组,控制访问权限。
  • 默认私有,添加 pub 关键字公开。
  • 子模块可以访问父模块私有成员,反之不行。
  • 同级模块,不能访问其他模块私有成员。
  • 同一模块,成员相互公开。

结构体可以为字段添加 pub,但枚举只能用于类型。

mod compiler { 
  pub mod checker {
    pub fn check() {
      println!("check!");
    }
  }

  pub mod builder {
    pub fn build() {
      println!("builder!");
    }

    pub fn test() {
      super::checker::check();  // 相对路径:父级模块
      self::build();      // 相对路径:当前模块
    }
  }
}

fn main() {
  crate::compiler::builder::test();  // 绝对路径。
}

可用 pub(super) 指定仅父模块及其后代可见,或 pub(in <path>) 指定更早的祖先路径。

mod compiler { 
  pub(in crate::compiler) mod checker {  // pub(super)
  }

  pub mod builder {
  }
}

名字导入

使用 use 关键字,将其他模块成员导入(import)当前作用域。

  • use mod::member 导入其他模块成员。
  • use mod::member as newname 重命名。
  • use mod::{member1, member2} 多个成员。
  • use mod::* 全部。
  • use ::<external_crate>::mod 强调导入外部模块,避免和内部重名。

查找次序:当前文件,同名源文件(example.rs),同名子目录(example/mod.rs)。

fn main() {
  use compiler::builder::{build, test};
  build();
  test();
}

组合导入多个成员。

use std::cmp::Ordering;
use std::io;

use std::{cmp::Ordering, io}; // !!!!
use std::io;
use std::io::Write;

use std::io::{self, Write};

重新导出 :以 pub use 导入的名字,可被外部访问。

mod test {
  pub use std::mem::size_of_val;
}


fn main() {
  assert_eq!(test::size_of_val(&1), 4);
}

鉴于标准库(std)某些成员被频繁使用,所以编译器会做一些隐式处理。类似 Python 解释器自动导入 __builtins__,并引入内置成员的做法。

  • 为每个 crate 注入 extern crate std;
  • 为每个 module 注入 use std::prelude::v1::*;

有关 prelude 导入的具体内容,参考《 The Rust Prelude 》。第三方(包括 std 其他模块)定义的 prelude,需显式导入,不会自动处理。

模块文件

可将模块拆分到不同文件。每个源码文件构成一个 同名模块 ,而子目录名则构成 嵌套关系

  • mod 载入子模块,构建模块树,指示编译文件列表。
  • 以相对或绝对路径访问模块树,而非文件名。
  • 在根文件内, crate 模块代表其自身。
  • 同一包内,main.rs 如同外部用户,以包名引用 lib.rs 模块树成员。
$ tree
.
├── compiler
│   ├── builder.rs
│   └── checker.rs
├── compiler.rs
└── main.rs

将 compiler 模块分离到独立文件内,并创建同名子目录保存其内部子模块。

提示, mod builder; 已将模块名导入,可用绝对路径访问其所属成员。

// compiler.rs

/*
   加载子模块,构建模块树。
 */

pub mod builder;
pub mod checker;
// compiler/checker.rs

pub fn check() {
  println!("check!");
}
// compiler/builder.rs

pub fn build() {
  println!("builder!");
}

最终,在根文件内完成树结构。

// main.rs

/*
   mod <...>; 不能放在语句块内。
  use <...>; 导入模块成员名到当前作用域。
 */

mod compiler;
use compiler::checker::check;
use compiler::builder::build;

fn main() {
  check();
  build();
}

2018: Path clarity

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文