サーチ…
構文
- mod modname ; //同じディレクトリ内のmodname .rsまたはmodname /mod.rsでモジュールを検索する
- mod modname { ブロック }
モジュールツリー
ファイル:
- example.rs (root of our modules tree, generally named lib.rs or main.rs when using Cargo)
- first.rs
- second/
- mod.rs
- sub.rs
モジュール:
- example -> example
- first -> example::first
- second -> example::second
- sub -> example::second::sub
- third -> example::third
example.rs
pub mod first;
pub mod second;
pub mod third {
...
}
second
のモジュールはexample.rs
ファイルで宣言されなけれexample
なりません。親モジュールはexample
で、 first
のモジュールではないため、 first.rs
ファイルや同じディレクトリレベルの別のファイルでは宣言できません
second/mod.rs
pub mod sub;
#[path]属性
Rustの#[path]
属性を使用して、特定のモジュールが標準の場所にない場合に検索するパスを指定することができます。しかし、これはモジュール階層を壊れやすくし、まったく別のディレクトリにファイルを移動することでビルドを簡単に破ることができるため、 一般的には推奨されません 。
#[path="../path/to/module.rs"]
mod module;
コードの名前と `use`の名前
use
ステートメントの名前の二重コロン構文は、コードの他の場所で使用されている名前と似ていますが、これらのパスの意味は異なります。
デフォルトでuse
ステートメント内の名前は、クレートルートから始まる絶対パスとして解釈されます。コード内の他の場所の名前は、現在のモジュールに関連しています。
ステートメント:
use std::fs::File;
モジュールと同様にクレートのメインファイルと同じ意味を持ちます。一方、 std::fs::File::open()
ような関数名は、コード内の名前が現在のモジュールとの相対的な意味で解釈されるため、クレートのメインファイルでのみRustの標準ライブラリを参照します。
fn main() {
std::fs::File::open("example"); // OK
}
mod my_module {
fn my_fn() {
// Error! It means my_module::std::fs::File::open()
std::fs::File::open("example");
// OK. `::` prefix makes it absolute
::std::fs::File::open("example");
// OK. `super::` reaches out to the parent module, where `std` is present
super::std::fs::File::open("example");
}
}
std::…
namesをどこにでも追加することができるようにするには:
use std;
逆に、 self
キーワードまたはsuper
キーワードの前に接頭辞を付けることによって、相対パスをuse
ことができます。
use self::my_module::my_fn;
親モジュールへのアクセス
時には、関数や構造体をプロジェクト内で絶対パスで何もuse
なく、インポートすると便利なことがあります。これを実現するには、次のようにsuper
モジュールを使用できます。
fn x() -> u8 {
5
}
mod example {
use super::x;
fn foo() {
println!("{}", x());
}
}
super
モジュールを複数回使用して現在のモジュールの「祖父母」に到達することができますが、1回のインポートでsuper
何度も使用すると、読みやすさの問題が生じることに注意する必要があります。
輸出と視認性
ディレクトリ構造:
yourproject/
Cargo.lock
Cargo.toml
src/
main.rs
writer.rs
main.rs
// This is import from writer.rs
mod writer;
fn main() {
// Call of imported write() function.
writer::write()
// BAD
writer::open_file()
}
作家.rs
// This function WILL be exported.
pub fn write() {}
// This will NOT be exported.
fn open_file() {}
基本コード編成
コードベースが大きくなったときに、コードをどのように整理するかを見てみましょう。
01.機能
fn main() { greet(); } fn greet() { println!("Hello, world!"); }
02.モジュール - 同じファイル内
fn main() { greet::hello(); } mod greet { // By default, everything inside a module is private pub fn hello() { // So function has to be public to access from outside println!("Hello, world!"); } }
03.モジュール - 同じディレクトリ内の別のファイルにある
いくつかのコードを新しいファイルに移動するとき、 mod
宣言でコードをラップする必要はありません。ファイル自体はモジュールとして機能します。
// ↳ main.rs mod greet; // import greet module fn main() { greet::hello(); }
// ↳ greet.rs pub fn hello() { // function has to be public to access from outside println!("Hello, world!"); }
いくつかのコードを新しいファイルに移動するとき、そのコードが
mod
宣言からラップされていれば、それはファイルのサブモジュールになります。
// ↳ main.rs mod greet; fn main() { greet::hello::greet(); }
// ↳ greet.rs pub mod hello { // module has to be public to access from outside pub fn greet() { // function has to be public to access from outside println!("Hello, world!"); } }
04.モジュール - 別のディレクトリにある別のファイル
一部のコードを別のディレクトリの新しいファイルに移動すると、ディレクトリ自体がモジュールとして動作します。モジュールルートのmod.rs
は、ディレクトリモジュールのエントリポイントです。そのディレクトリ内の他のすべてのファイルは、そのディレクトリのサブモジュールとして機能します。
// ↳ main.rs mod greet; fn main() { greet::hello(); }
// ↳ greet/mod.rs pub fn hello() { println!("Hello, world!"); }
モジュールルートに複数のファイルがある場合は、
// ↳ main.rs mod greet; fn main() { greet::hello_greet() }
// ↳ greet/mod.rs mod hello; pub fn hello_greet() { hello::greet() }
// ↳ greet/hello.rs pub fn greet() { println!("Hello, world!"); }
05.モジュール - self
fn main() { greet::call_hello(); } mod greet { pub fn call_hello() { self::hello(); } fn hello() { println!("Hello, world!"); } }
06.モジュール - super
- モジュールの内部からルート関数にアクセスするには、
fn main() { dash::call_hello(); } fn hello() { println!("Hello, world!"); } mod dash { pub fn call_hello() { super::hello(); } }
- ネストしたモジュールの内部から外部/親モジュールの関数にアクセスする場合は、
fn main() { outer::inner::call_hello(); } mod outer { pub fn hello() { println!("Hello, world!"); } mod inner { pub fn call_hello() { super::hello(); } } }
07.モジュール - use
- フルパスを新しい名前にバインドする場合は、
use greet::hello::greet as greet_hello; fn main() { greet_hello(); } mod greet { pub mod hello { pub fn greet() { println!("Hello, world!"); } } }
- クレートスコープレベルのコンテンツを使用する場合
fn main() { user::hello(); } mod greet { pub mod hello { pub fn greet() { println!("Hello, world!"); } } } mod user { use greet::hello::greet as call_hello; pub fn hello() { call_hello(); } }