與 Rust 勾心鬥角 · 小工程

garfileo發表於2022-05-16

程式碼寫了二百多行了,雖然不多,但是統統放在一份原始檔裡,無論是閱讀還是修改,已經讓我覺得眼累。現在我要嘗試使用 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。

相關文章