[解決済み] モジュールを複数のファイルに分割する
質問
複数の構造体を含むモジュールを作成したい。
をそれぞれ独自のファイルに格納したい。
を使うことで
Math
モジュールを例にしています。
Math/
Vector.rs
Matrix.rs
Complex.rs
各構造体は同じモジュールに収めたいので、メインファイルから以下のように使用します。
use Math::Vector;
fn main() {
// ...
}
しかし、Rustのモジュールシステムは(そもそもちょっとわかりにくいのですが)、これを行うための明白な方法を提供していません。モジュール全体を1つのファイルにまとめることしかできないようです。これは錆びないのでしょうか?そうでないなら、どうすればいいのでしょうか?
どのように解決するのですか?
Rustのモジュールシステムは実は信じられないほど柔軟で、コードがファイルでどのように構成されているかを隠しつつ、好きな種類の構造を公開することができます。
ここでの鍵は
pub use
を利用することです。これにより、他のモジュールから識別子を再輸出することができます。これにはRustの
std::io
クレートで、サブモジュールからのいくつかの型は
で使用するために再エクスポートされます。
std::io
.
Edit (2019-08-25): 答えの以下の部分はかなり前に書かれたものです。このようなモジュール構造を
rustc
だけでこのようなモジュール構造をセットアップする方法を説明しています。今日では、ほとんどのユースケースでCargoを使用するのが普通でしょう。以下はまだ有効ですが、その一部(例えば#![crate_type = ...]
) は奇妙に見えるかもしれません。これは推奨される解決策ではありません。
あなたの例に合わせるために、このディレクトリ構造で始めることができます。
src/
lib.rs
vector.rs
main.rs
ここで、あなたの
main.rs
:
extern crate math;
use math::vector;
fn main() {
println!("{:?}", vector::VectorA::new());
println!("{:?}", vector::VectorB::new());
}
そして、あなたの
src/lib.rs
:
#[crate_id = "math"];
#[crate_type = "lib"];
pub mod vector; // exports the module defined in vector.rs
そして最後に
src/vector.rs
:
// exports identifiers from private sub-modules in the current
// module namespace
pub use self::vector_a::VectorA;
pub use self::vector_b::VectorB;
mod vector_b; // private sub-module defined in vector_b.rs
mod vector_a { // private sub-module defined in place
#[derive(Debug)]
pub struct VectorA {
xs: Vec<i64>,
}
impl VectorA {
pub fn new() -> VectorA {
VectorA { xs: vec![] }
}
}
}
そして、ここでマジックが起こります。私たちはサブモジュール
math::vector::vector_a
というサブモジュールを定義し、特殊なベクトルを実装しています。しかし、あなたのライブラリのクライアントには、このような
vector_a
サブモジュールがあることは気にしないでください。その代わり、私たちはそれを
math::vector
モジュールで利用できるようにします。これを行うには
pub use self::vector_a::VectorA
を再エクスポートします。
vector_a::VectorA
の識別子を現在のモジュールに再エクスポートします。
しかし、特別なベクターの実装を別のファイルに置くことができるように、これをどのように行うか質問しました。これは
mod vector_b;
行が行うことです。これは、Rust コンパイラに
vector_b.rs
ファイルを探すように指示します。そして案の定、ここに私たちの
src/vector_b.rs
ファイルです。
#[derive(Debug)]
pub struct VectorB {
xs: Vec<i64>,
}
impl VectorB {
pub fn new() -> VectorB {
VectorB { xs: vec![] }
}
}
クライアントの立場からすると、このように
VectorA
と
VectorB
が2つの異なるファイルの2つの異なるモジュールで定義されていることは、完全に不透明です。
もし、同じディレクトリにある
main.rs
で実行できるはずです。
rustc src/lib.rs
rustc -L . main.rs
./main
一般に "クレートとモジュール" の章を参照してください。 の章はかなり良いです。たくさんの例があります。
最後に、Rustコンパイラはサブディレクトリの中も自動で探してくれます。 例えば、上記のコードはこのディレクトリ構造で変更なく動作します。
src/
lib.rs
vector/
mod.rs
vector_b.rs
main.rs
コンパイルと実行のコマンドも同じです。
関連
-
[解決済み] モジュールレイアウトバージョンの非互換性
-
[解決済み] Verilog エラー。構造ネット式に接続する必要があります
-
[解決済み] Pythonモジュールをアンロード(再ロード)するにはどうしたらいいですか?
-
[解決済み] PythonモジュールとPythonパッケージの違いは何ですか?
-
[解決済み] Pythonモジュールのソースの場所を見つけるにはどうしたらいいですか?
-
[解決済み] クラスとモジュールの違い
-
[解決済み】Node.jsで循環的な依存関係に対処する方法
-
[解決済み] 与えられた(数値)分布で乱数を発生させる
-
[解決済み] ES6 オブジェクトからすべての値をエクスポートする
-
[解決済み] モジュールファイルをまたいでマクロを使用するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン