はじめに
Rust にはモジュールというプログラムをファイルやフォルダに分割して管理する仕組みがあります。
これを使うとプログラムをわかりやすく整理できるのですが、ある問題があります。
この記事ではその解決方法を示します。
開発環境
macOS Monterey(v12.5.1)
rustc 1.69.0 (84c898d65 2023-04-16)
問題
この記事で解決したい問題がどんなシチュエーションで発生するかをまず説明します。
以下のようにプロジェクトを用意します。
cargo new rsmodule
この時点では以下のようなファイル構造になっているはずです。
- rsmodule
- src
- main.rs
- src
main.rsを以下の様に書き換えます。
この時点ではモジュールを分割していないので、何の問題もなく main.rs
から MyStruct
を参照できます。
struct MyStruct {
name: String
}
fn main() {
let myStr = MyStruct { name: String::from("desktopgame") };
println!("my name is {}.", myStr.name);
}
次に、 my_module
というモジュールを作成してそこに MyStruct
を移動させます。
以下の様なファイル構造となります。
- rsmodule
- src
- my_module
- my_struct.rs
- my_module.rs
- main.rs
- my_module
- src
my_struct.rs
では構造体を宣言します。
pub struct MyStruct {
pub name: String
}
そして my_module.rs
から my_struct.rs
を参照させます。
pub mod my_struct;
すると、main.rs
から以下の様に参照できるはずです。
mod my_module;
fn main() {
let myStr = my_module::my_struct::MyStruct { name: String::from("desktopgame") };
println!("my name is {}.", myStr.name);
}
これでは少々冗長です。そこで以下の様に書き換えることができます。
mod my_module;
use my_module::my_struct::MyStruct;
fn main() {
let myStr = MyStruct { name: String::from("desktopgame") };
println!("my name is {}.", myStr.name);
}
しかしこれも私のやりたいこととは違っています。
私としては my_module::MyStruct
として参照させたいのです。
そこで pub use
を使った方法を紹介します。
解決方法
my_module.rs
を以下の様に書き換えます。
mod my_struct;
pub use my_struct::MyStruct;
これで main.rs
からは以下の様に参照できます。
mod my_module;
fn main() {
let myStr = my_module::MyStruct { name: String::from("desktopgame") };
println!("my name is {}.", myStr.name);
}
この書き方だと、 my_module::my_struct::MyStruct
としての参照はできなくなります。
my_module.rs
で pub mod
として宣言していないからです。
ネストしたい場合
my_module
の下にさらに sub_module
というモジュールを生やしたいとします。
ファイル構造は以下の様になります。
- rsmodule
- src
- my_module
- sub_module
- sub_struct.rs
- sub_module.rs
- my_struct.rs
- sub_module
- my_module.rs
- main.rs
- my_module
- src
sub_struct.rs
での型宣言は先ほどと同じです。
pub struct SubStruct {
pub name: String
}
sub_module.rs
から sub_struct.rs
を参照します。
これも先ほどと同様です。
mod sub_struct;
pub use sub_struct::SubStruct;
最後に my_module
から sub_module
を pub mod
で参照させます。
mod my_struct;
pub use my_struct::MyStruct;
pub mod sub_module;
すると main.rs
からは my_module::sub_module::SubStruct
として参照できます。
mod my_module;
fn main() {
let myStr = my_module::MyStruct { name: String::from("desktopgame") };
println!("my name is {}.", myStr.name);
let myStr2 = my_module::sub_module::SubStruct { name: String::from("desktopgame") };
println!("my name is {}.", myStr2.name);
}