モジュールを追加する

モジュール [Rustリファレンス] はRustのコードの単位で、カプセル化とプライバシー制御の境界にもなります。本セクションではモジュールの種類と、各種類のモジュールを追加する方法について解説します。

ルートモジュール

最初に意識しておきたいのが、Rustプロジェクトを追加して最初に現れる src/lib.rs ファイルがルートモジュールであるという点です。

ルートモジュールのパスは常に crate です。以下の例で示されているように、このモジュールで定義されている項目は crate::greet のようにして参照します。(root_taskRustタスクを追加する で追加した関数です。)

src/lib.rs
// core ------ ...
// std ------- ...
// crate --+-- root_task
//         |
//         '-- greet

#[no_mangle]
extern "C" fn root_task(_: usize) {
    // 現在モジュールのパスは `crate` なので、以下の2行は同等
    greet();
    crate::greet();
}

fn greet() {
    println!("Hello!");
}

モジュールツリーはルートモジュールと外部クレート (標準ライブラリクレートおよび他に追加したライブラリクレート) を根とした階層構造で構成されます。モジュールの中に mod 項目を記述することで子モジュールを宣言していきます。子モジュールの定義方法に応じてインラインモジュール非インラインモジュールがあります。

インラインモジュール

mod 項目に続けて定義を記述するタイプのモジュールをインラインモジュールと呼びます。前の例の greet 関数を mod greeter { ... } で囲ってみましょう。

// core ------ ...
// std ------- ...
// crate --+-- root_task
//         |
//         '-- greeter -- greet

#[no_mangle]
extern "C" fn root_task(_: usize) {
    // 現在モジュールのパスは `crate` なので、以下の2行は同等
    greeter::greet();
    crate::greeter::greet();
}

mod greeter {       // <-----
    pub(crate) fn greet() {
        println!("Hello!");
    }
}                   // <-----

この場合、 greet 関数の完全パスは crate::greeter::greet になります。デフォルトではモジュール内で定義された項目は外からはアクセスできません。ここでは pub(crate) を指定することで、 crate とその子孫モジュールからアクセスできるようにしています。

非インラインモジュール

もっと一般的なモジュールの定義方法は、外部のソースファイルで定義する方法です。このタイプのモジュールを非インラインモジュールと呼びます。

非インラインモジュールのソースファイルのパスは2種類の方式があります。

  1. mod-rs方式: ルートモジュール (src/lib.rs, etc.) および 名前/mod.rs のようなパスのソースファイルがこれに該当します。子モジュールは同じディレクトリで定義します (e.g., 名前/.rs)。

  2. non-mod-rs方式: mod.rs 以外の名前のソースファイル (e.g., 名前.rs) がこれに該当します。子モジュールは兄弟ディレクトリ内で定義します (e.g., 名前/.rs)。子モジュールがなければこのディレクトリは不要です。

../../_images/mod-rs-source-file.svg

Note

ルートモジュール以外に関してはnon-mod-rs方式を採用することが推奨されています。理由の一つとして、mod-rs方式ではテキストエディタやIDE上で mod.rs という表題のタブが並んでしまうことが挙げられます。

前のコード例のインラインモジュールをIDE上でnon-mod-rs方式の非インラインモジュールに変換するには、次の手順を踏みます。

  1. ルートモジュール src/lib.rs はmod-rs方式なので、その子モジュールは src 内に作成します。 ソリューション エクスプローラーsrc を右クリックし、 追加(D) ‣ 新しい項目(W) から .rs を選択し、名前を設定後、 追加(A) をクリックします。

    ../../_images/new-module-source-file.png

    Note

    基本的にはファイル名がそのままモジュール名になります。この場合、 greeter.rs という名前にしてください。


  1. 親モジュール内 (src/lib.rs, crate) で、この子モジュールを宣言します。これはセミコロンで終わる形 (mod greeter;) で mod 項目を記述することで行います。

    #[no_mangle]
    extern "C" fn root_task(_: usize) {
        // 現在モジュールのパスは `crate` なので、以下の2行は同等
        greeter::greet();
        crate::greeter::greet();
    }
    
    mod greeter;    // <-----
    

注意

単にソースファイルを追加するだけではモジュールツリーには追加されず、コンパイル対象になりません。上記のように必ず mod 項目を追加するようにしてください。


  1. 子モジュール (src/greeter.rs, crate::greeter) の内容を定義します。

    pub(crate) fn greet() {
        println!("Hello!");
    }
    

孫モジュール

に続けて、さらに crate::greeter の子モジュール crate::greeter::inner (crate からの視点では孫モジュール) も作成する手順を見てみましょう。この子モジュールも同じくnon-mod-rs方式で作成します。

  1. 親モジュール (src/greeter.rs, crate::greeter) 内で子モジュールを宣言します。

    mod inner;      // <-----
    
    pub(crate) fn greet() {
        println!("Hello!");
    }
    

  1. src/greeter.rs はnon-mod-rs方式なので、子モジュールは src/greeter/ 内に作成します。 ソリューション エクスプローラーsrc を右クリックし、 追加(A) ‣ 新しいフォルダー(D) を選択し、 greeter という名前のサブディレクトリを作成します。

    ../../_images/new-module-source-dir.png

  1. 作成したディレクトリ内に子モジュールのソースファイル inner.rs を作成します。このソースファイルが crate::greeter::inner となります。

    ../../_images/new-module-source-dir2.png

さらに詳しく