モジュールを複数のファイルに分割する

この章のすべての例において、今までのところ、複数のモジュールを一つのファイルに定義していました。 モジュールが大きくなる時、コードを読み進めやすくするため、それらの定義を別のファイルへ移動させたくなるかもしれません。

例えば、Listing 7-17 のコードからはじめましょう。クレートルートのファイルをListing 7-21 のコードを持つように変更して、front_of_houseモジュールをそれ専用のファイルsrc/front_of_house.rsに動かしましょう。 今回、クレートルートファイルはsrc/lib.rsですが、この手続きはクレートルートファイルがsrc/main.rsであるバイナリクレートでもうまく行きます。

ファイル名: src/lib.rs

mod front_of_house;

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}

Listing 7-21: front_of_houseモジュールを宣言する。その中身はsrc/front_of_house.rs内にある

そして、 Listing 7-22 のように、src/front_of_house.rs にはfront_of_house モジュールの中身の定義を与えます。

ファイル名: src/front_of_house.rs

pub mod hosting {
    pub fn add_to_waitlist() {}
}

Listing 7-22: src/front_of_house.rsにおける、front_of_houseモジュール内部の定義

mod front_of_houseの後にブロックではなくセミコロンを使うと、Rustにモジュールの中身をモジュールと同じ名前をした別のファイルから読み込むように命令します。 私達の例で、つづけてhostingモジュールをそれ専用のファイルに抽出するには、src/front_of_house.rshostingモジュールの宣言のみを含むように変更します:

ファイル名: src/front_of_house.rs

pub mod hosting;

さらにsrc/front_of_house ディレクトリとsrc/front_of_house/hosting.rs ファイルを作って、hostingモジュール内でなされていた定義を持つようにします。

ファイル名: src/front_of_house/hosting.rs


#![allow(unused)]
fn main() {
pub fn add_to_waitlist() {}
}

定義は別のファイルにあるにもかかわらず、モジュールツリーは同じままであり、eat_at_restaurant内での関数呼び出しもなんの変更もなくうまく行きます。 このテクニックのおかげで、モジュールが大きくなってきた段階で新しいファイルへ動かす、ということができます。

src/lib.rs におけるpub use crate::front_of_house::hosting という文も変わっていないし、useはどのファイルがクレートの一部としてコンパイルされるかになんの影響も与えないということに注意してください。 modキーワードがモジュールを宣言したなら、Rustはそのモジュールに挿入するためのコードを求めて、モジュールと同じ名前のファイルの中を探すというわけです。

まとめ

Rustでは、パッケージを複数のクレートに、そしてクレートを複数のモジュールに分割して、あるモジュールで定義された要素を他のモジュールから参照することができます。 これは絶対パスか相対パスを指定することで行なえます。 これらのパスはuse文でスコープに持ち込むことができ、こうすると、そのスコープで要素を複数回使う時に、より短いパスで済むようになります。 モジュールのコードは標準では非公開ですが、pubキーワードを追加することで定義を公開することができます。

次の章では、きちんと整理されたあなたのコードで使うことができる、標準ライブラリのいくつかのコレクションデータ構造を見ていきます。