// dictionary
モジュール.
モジュールは、modキーワードで定義する、項目(item)を0個以上入れられる入れ物です1。関連する関数や構造体をひとまとめにして名前を付けられるため、読み手は定義を全部読まなくてもグループ単位で目的のコードを探せます2。
モジュールが担うのはコードの整理とプライバシー境界の2つの役割です。Rustでは項目はデフォルトで非公開で、モジュールの中身は親モジュールからは見えません23。modの{}は名前空間の区切りであると同時に、外から触れる範囲を決める壁でもあります。
mod shop {
// 非公開のまま。shop自身とその子孫からは使えるが、外からは見えない
const TAX_RATE: u32 = 10;
// モジュールはネストできる
pub mod cart {
pub fn total(prices: &[u32]) -> u32 {
let subtotal: u32 = prices.iter().sum();
subtotal * (100 + crate::shop::TAX_RATE) / 100
}
}
}
fn main() {
// モジュール名を `::` でたどって呼び出す
println!("税込合計: {}円", shop::cart::total(&[980, 1250]));
}Playgroundで開く上のコードのように{}で中身をその場に書くモジュールをインラインモジュールと呼びます。mod cart;とセミコロンで終えれば、本体は外部ファイルから読み込まれます(モジュールのファイル分割)1。
モジュールツリー
モジュールは任意の深さにネストでき1、クレートの中身はクレートルートを頂点とするツリーになります2。上のコードのツリーは次の形です。
crate
└── shop // 非公開
├── TAX_RATE // 非公開
└── cart // pub
└── total // pub
頂点にあるルートモジュールはそれ自体に名前がなく、パス(Path)の先頭にcrateと書いて起点にします。ツリー上の項目は、そこからモジュール名をたどって参照します。
プライバシー境界
非公開の項目にアクセスできるのは、それを定義したモジュールとその子孫だけです3。子モジュールからは祖先の非公開の項目が見える一方、親から子の非公開の項目は見えません。実装の詳細をモジュールの内側に隠したまま、公開したいものだけをpubで外に出す設計ができます。
補足
外部ファイルから読み込むモジュール
mod cart;とセミコロンで終えたモジュールは、本体を外部ファイルから読み込みます。ファイルのパスは既定で論理的なモジュールパスをそのまま写した形になり、祖先のモジュールはディレクトリになります1。クレートルートに書いたmod cart;ならsrc/cart.rs、shopの中に書いたならsrc/shop/cart.rsです(モジュールのファイル分割も参照)。
インラインモジュールは、テスト用のmod testsのように、対象のコードと同じファイルに置いておきたい小さなまとまりに向いています。
モジュールは型の名前空間に属する
モジュールは、それが置かれたモジュールやブロックの型名前空間に定義されます1。同じ名前空間に同名の項目は複数定義できないため1、同じモジュール内にmod shopとstruct shopは共存できません(E0428)。一方、値の名前空間に属するfn shopとは名前が衝突しません(Rust 1.93で確認)。
Footnotes
この辞書が使われているページ
backlinks 9