与 Rust 勾心斗角 · 小工程

代码写了二百多行了,虽然不多,但是统统放在一份源文件里,无论是阅读还是修改,已经让我觉得眼累。现在我要尝试使用 Rust 语言的模块功能为它们分家。

众所周知,Rust 的模块功能通常是配合它的搭档——项目构建工具 Cargo 来用,但我不打算如此。因为我不喜欢做一点小事情,就要大动干戈。这不是 Cargo 的问题,这是我的问题。

rskynet 项目

新建一个目录 rskynet,在该目录新建一份文件 rskynet.rs,其内容为

mod geometry;
use geometry::{sphere, mesh};

fn main() {
    sphere::hi();
    mesh::hi();
}

项目的名字就叫 rskynet。在 rskynet.rs 文件里,mod geometry 语句可「载入」 geometry 模块,use 语句可将 geometry 模块的子模块 sphere 和 mesh 作为命名空间。在 main 函数里,分别调用了 sphere 和 mesh 模块里的 hi 函数。

geometry 模块

在 rskynet 目录内,建立 geometry 目录,然后在该目录内新建一份文件 mod.rs,其内容如下:

pub mod sphere {
    // 内容暂时为空
}

pub mod mesh {
    // 内容暂时为空
}

现在,rskynet 目录的布局概览如下

rskynet
├── geometry
│   └── mod.rs
└── rskynet.rs

在 rskynet 目录内编译 rskynet.rs 并运行所得程序:

$ rustc rskynet.rs
$ ./rskynet

结果会输出

我是球体!
我是网格!

rustc 在编译 rskynet.rs 时,能够找到 geometry/mod.rs 文件,并且认为它是 geometry 模块,并且能够认出 geometry 模块还有两个子模块 sphere 和 mesh。

现在,可以得出以下结论:

  • 模块可以是「目录/mod.rs」的形式;
  • 在一个模块里,使用 pub mod 模块名 {...} 的语法可以构造该模块的子模块。

继续分割

能否将 sphere 和 mesh 模块的代码从 geometry/mod.rs 里抽出来,放在单独的文件里呢?试试看。

在 geometry 目录新建一份文件,名为 sphere.rs,其内容为

pub fn hi() {
    println!("我是球体!");
}

再在 geometry 目录新建一份文件,名为 mesh.rs,其内容为

pub fn hi() {
    println!("我是网格!");
}

然后将 geometry/mod.rs 内容修改为

pub mod sphere;
pub mod mesh;

最后重新编译 rskynet.rs 并运行所得程序,结果与上次相同。据此,可得结论:一份 .rs 文件是一个模块,若它被同目录内的 mod.rs 文件 pub mod,则它会成为 mod.rs 对应模块的子模块。

访问父模块

倘若将 geometry/mod.rs 内容修改为

pub fn hi() {
    println!(">>>");
}

pub mod sphere;
pub mod mesh;

在 sphere 和 mesh 模块里该如何调用它们父模块里的这个 hi 函数呢?

答案是,用 super 指代父模块。例如,将 sphere.rs 内容修改为

pub fn hi() {
    super::hi();
    println!("我是球体!");
}

在 main 函数里调用 sphere::hi 函数时,可输出

>>>
我是球体!

真正的 rskynet 项目

https://gitee.com/garfileo/rskynet

小结

谁知道我能坚持多久不用 Cargo。

你可能感兴趣的