コード編成の背後にある概念を理解する
開始する前に、Rust プログラムでのコード編成の背後にある概念について説明することが重要です。
- パッケージ:
- 1 つ以上の "クレート" 内に機能が含まれています。
- これらの "クレート" をビルドする方法に関する情報が含まれています。 情報は
Cargo.toml
ファイル内にあります。
- クレート:
- コンパイル単位です。これは、Rust コンパイラが動作できる最小のコード量です。
- コンパイルが完了すると、実行可能ファイルまたはライブラリが生成されます。
- 暗黙的な、名前のないトップレベル "モジュール" が含まれています。
- モジュール:
- "クレート" 内の "(入れ子になっている可能性がある)" コード編成の単位です。
- 追加のモジュールにまたがる再帰的な定義が含まれる場合があります。
パッケージ
コマンド $ cargo new <project-name>
を実行するたびに、Cargo によってパッケージが作成されます。
$ cargo new my-project
Created binary (application) `my-project` package
ここでは、src/main.rs
のみが含まれているパッケージを使用しています。つまり、my-project
という名前のバイナリ クレートだけが含まれています。
my-project
├── src
│ └── main.rs
└── Cargo.toml
パッケージは、src/bin
ディレクトリにファイルを配置することで、複数のバイナリ クレートを持つことができます。 各ファイルが個別のバイナリ クレートになります。
パッケージ内に src/main.rs
と src/lib.rs
がある場合は、ライブラリとバイナリという 2 つのクレートが含まれています。 これらの両方にパッケージと同じ名前が付けられています。
クレート
Rust のコンパイル モデルは、バイナリまたはライブラリにコンパイルできる、"クレート" と呼ばれる成果物を中心にしています。
cargo new
コマンドを使用して作成したすべてのプロジェクトが、クレートそのものです。 プロジェクト内で依存関係として使用できるサードパーティーのすべての Rust コードも、それぞれが 1 つのクレートです。
ライブラリ クレート
バイナリ プログラムを作成する方法については既に説明しましたが、ライブラリの作成も簡単です。 ライブラリを作成するには、--lib
コマンドライン パラメーターを cargo new
コマンドに渡します。
$ cargo new --lib my-library
Created library `my-library` package
src/main.rs
ファイルの代わりに、=src/lib.rs' ファイルが取得されていることを確認できます。
my-library
├── src
│ └── lib.rs
└── Cargo.toml
このクレートをコンパイルするように Cargo に指示すると、libmy_library.rlib
という名前のライブラリ ファイルが作成され、他のプロジェクトにパブリッシュしてリンクすることができます。
モジュール
Rust は、階層的に論理的なユニットに分割し、読みやすく再利用しやすい、強力なモジュール システムを提供します。
モジュールは、以下の項目のコレクションです。
- 定数
- 型の別名
- 関数
- 構造体
- 列挙型
- Traits
impl
のブロック- その他のモジュール
モジュールは、項目の "プライバシー" も制御します。 項目のプライバシーにより、項目が "公開" または "非公開" のいずれかとして識別されます。 公開は、項目が外部コードで使用できることを意味します。 非公開は、項目が内部実装の詳細であり、外部で使用できないことを意味します。
モジュールの例を示します。
mod math {
type Complex = (f64, f64);
pub fn sin(f: f64) -> f64 { /* ... */ }
pub fn cos(f: f64) -> f64 { /* ... */ }
pub fn tan(f: f64) -> f64 { /* ... */ }
}
println!("{}", math::cos(45.0));
ソース ファイルに mod
宣言が含まれている場合は、これにコンパイラを実行する前に、ソース ファイル内の mod
宣言がある場所にモジュール ファイルの内容が挿入されます。 つまり、モジュールは個別にはコンパイルされず、クレートのみがコンパイルされます。
math
モジュールの関数定義の先頭に、pub
キーワードがあることにお気づきかもしれません。
Rust コンパイラによって、項目がモジュール間で使用できるかどうかが確認されます。 既定では、Rust 内のすべてのものがプライベートであり、現在のモジュールとその子孫のみがアクセスできます。 これに対して、項目が pub
として宣言されている場合は、外部からアクセスできると考えることができます。 次に例を示します。
// Declare a private struct
struct Foo;
// Declare a public struct with a private field
pub struct Bar {
field: i32,
}
// Declare a public enum with two public variants
pub enum State {
PubliclyAccessibleVariant,
PubliclyAccessibleVariant2,
}
Rust のプライバシー規則は、内部実装の詳細を非表示にしながら、パブリック API を公開するモジュール階層を作成する場合に、驚くような力を発揮します。