Rustのモジュールシステム: Package、CrateとModule
Rustのモジュールシステムを徹底解説:Package、Crate、Module、pubによる公開範囲制御、useによるパスのスコープ導入。
Rustのプロジェクトが単一ファイルを超えて成長するにつれて、コードの整理とスコープ管理が極めて重要になります。Rustはカプセル化、プライバシー、再利用性を両立する強力なモジュールシステムを提供しています。
10歳でもわかる説明:おもちゃ工場と各部門#
大きなおもちゃ工場を建てる場面をイメージしてください:
- Package (
Cargo.toml): 工場敷地全体であり、設計図、納品伝票、工具一式を含んでいます。 - Crate (クレート): クライアントやお客さんにそのまま出荷できる完成品の輸送コンテナ(実行可能バイナリまたはライブラリ)。
- Module (モジュール): 工場内の個別の部屋・作業部門(例:木工部門、塗装部門、品質管理室)。
- 公開範囲 (
pub): 鍵のかかった作業ドア(private)と、来客用の受付窓口(pub)。Rustでは安全のため、初期状態ですべてのドアに鍵がかかっています。
graph TD
subgraph Package ["Package (Cargo.toml)"]
subgraph BinaryCrate ["Binary Crate (src/main.rs)"]
MainFn["main() entry point"]
end
subgraph LibraryCrate ["Library Crate (src/lib.rs)"]
RootMod["Crate Root (crate::)"]
RootMod --> ModFront["mod front_of_house"]
ModFront --> ModHosting["pub mod hosting"]
ModHosting --> FnAdd["pub fn add_to_waitlist()"]
RootMod --> ModBack["mod back_of_house"]
ModBack --> FnCook["fn fix_incorrect_order()"]
end
end
MainFn -->|use restaurant::front_of_house::hosting| FnAdd
階層構造の定義#
| 単位 | 定義 | ファイル配置ルール |
|---|---|---|
| Package | 1つ以上のCrateのビルド方法を記述した Cargo.toml を含む Cargo の機能単位。 | Cargo.toml が置かれたルートディレクトリ |
| Crate | ライブラリまたは実行可能バイナリを生成するモジュールツリー。 | src/main.rs (バイナリ) または src/lib.rs (ライブラリ) |
| Module | コードをグループ化し、内部要素の公開・非公開を制御する単位。 | インライン mod name { ... } または src/name.rs |
| Path | モジュールツリー内の要素(構造体・関数など)を指定するパス。 | crate::front_of_house::hosting::add_to_waitlist() |
モジュールとプライバシールール#
Rustにおいて、すべての要素(関数、メソッド、構造体、列挙型、モジュール)はデフォルトで親モジュールに対して非公開(private)です。
graph LR
Parent["親モジュール"] -->|子モジュールのすべてを参照可能| Child["子モジュール"]
Child -->|非公開の兄弟要素は参照不可| Sibling["兄弟要素"]
Child -->|親モジュールの要素は常に参照可能| Parent
レストラン業務の例#
src/lib.rs
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
fn seat_at_table() {} // private: hosting内部でのみ呼び出し可能
}
mod serving {
fn take_order() {}
fn serve_order() {}
fn take_payment() {}
}
}
pub fn eat_at_restaurant() {
// クレートルートからの絶対パス
crate::front_of_house::hosting::add_to_waitlist();
// 現在のモジュールからの相対パス
front_of_house::hosting::add_to_waitlist();
}rust[!NOTE] モジュールを
pub modにしても、公開されるのはモジュール自体へのアクセスのみです。内部の関数やフィールドは個別にpubを付与しない限り非公開のままです。
構造体と列挙型における pub の違い#
構造体と列挙型では、公開範囲の扱いが異なります:
- 構造体 (Struct):
pub structを指定しても名前が公開されるだけで、各フィールドは個別にpubを付けない限り非公開のままです。 - 列挙型 (Enum):
pub enumを指定すると、含まれるすべてのヴァリアント(列挙子)が自動的に公開されます。
src/lib.rs
mod back_of_house {
pub struct Breakfast {
pub toast: String, // 公開フィールド:客がトーストの種類を選択可能
seasonal_fruit: String, // 非公開フィールド:シェフが季節に応じて決定
}
impl Breakfast {
// seasonal_fruitが非公開のため、公開コンストラクタが必須
pub fn summer(toast: &str) -> Breakfast {
Breakfast {
toast: String::from(toast),
seasonal_fruit: String::from("peaches"),
}
}
}
#[derive(Debug)]
pub enum Appetizer {
Soup, // 自動的に公開
Salad, // 自動的に公開
}
}rustuse によるスコープ導入#
長いパスを何度も記述するのを防ぐため、use キーワードを使ってローカルスコープにシンボリックリンクのように要素を導入します:
src/lib.rs
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
// 関数は親モジュールを導入するのがRustの慣例
use crate::front_of_house::hosting;
// 構造体や列挙型は直接型名を導入
use std::collections::HashMap;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
let mut map = HashMap::new();
map.insert("table_1", "occupied");
}rustsequenceDiagram
participant Code as 呼び出し側コード
participant Scope as ローカルスコープ
participant CrateTree as クレートモジュールツリー
Note over Scope,CrateTree: use crate::front_of_house::hosting;
Scope->>CrateTree: hosting モジュールのパスを解決
CrateTree-->>Scope: 現在のスコープに別名 hosting を定義
Code->>Scope: hosting::add_to_waitlist()
Scope->>CrateTree: front_of_house::hosting::add_to_waitlist() を実行
pub use による再エクスポート#
use でスコープに導入した要素は現在のスコープ内で非公開です。pub use を使うことで外部の利用者に対しても公開でき、整った公開APIを設計できます:
src/lib.rs
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
// 再エクスポート: 外部から restaurant::hosting::add_to_waitlist() で直接利用可能
pub use crate::front_of_house::hosting;rustモジュールを複数ファイルに分割する#
プロジェクトが大きくなったら、ファイルシステムに対応させて分割管理します:
my_project/
├── Cargo.toml
└── src/
├── main.rs
├── lib.rs
└── front_of_house/
├── mod.rs (または front_of_house.rs)
└── hosting.rstextsrc/lib.rs
// front_of_house モジュールを宣言(Rustが src/front_of_house.rs を読み込み)
pub mod front_of_house;
pub use crate::front_of_house::hosting;rustsrc/front_of_house.rs
// hosting サブモジュールを宣言(Rustが src/front_of_house/hosting.rs を読み込み)
pub mod hosting;rustsrc/front_of_house/hosting.rs
pub fn add_to_waitlist() {
println!("ウェイティングリストに追加しました!");
}rustまとめ#
- Package は
Cargo.tomlで管理される1つ以上のCrateの集合体。 - Crate はバイナリまたはライブラリを出力するコンパイル単位。
- Module (
mod) はコードを階層的に整理し、アクセススコープを制御。 - すべての要素はデフォルトで非公開であり、
pubで明示的に公開。 useによる簡潔なスコープ導入とpub useによる洗練されたAPI再エクスポートを活用。