Rustのモジュールと名前空間まとめ

# はじめに

この記事は、[The Rust Programming language](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html)という本の7章を元にしています。

# まとめ

### 新しいcargoプロジェクトをbinary crateと共に作成する

```console:console
cargo new my-project
```

### 新しいcargoプロジェクトをlibrary crateと共に作成する

```
cargo new --lib my-project
```

### moduleの定義

moduleはネストできる。

```rust:module_example.rs
mod my_name_space {
    mod child_name_space {
        fn my_function1() {}
        fn my_function2() {}
    }
}
```

### module内の関数の呼び出し

- 先頭に`crate`を付ける場合は絶対パスでの指定になる。
そうでない場合は相対パスでの指定になる。

- 呼び出し元の関数よりネストしている関数や名前空間にアクセスするには、moduleや関数それぞれに`pub`キーワードが付いている必要がある。

```rust:call_example.rs
mod my_name_space {
    pub mod child_name_space {
        pub fn my_function() {}
    }
}

pub fn eat_at_restaurant() {
    crate::my_name_space::my_function();
    my_name_space::my_function();
}

```

### superキーワード

superキーワードは呼び出し元の関数の1つ上のパスを表す。

```rust:super_example.rs
fn parent_function()

mod my_namespace {
    fn my_function() {
        super::parent_function();
    }
}
```

### structに対するpub指定

structに対してはメンバ毎にpubキーワードを指定する必要がある

```rust:struct_example.rs
mod my_module {
    pub struct MyStruct {
        pub member_var1 : Int,
        member_var2 : Int,
    }
    impl MyStruct{
        pub fn create() -> MyStruct {
            MyStruct {
                member_var1: 5
                member_var2: 8
            }
        }
    }
}
pub fn my_function() {
    let mut instance = my_module::MyStruct::create();
    instance.member_var1 = 12
    //エラー！
    //instance.member_var2 = 15
}
```

### enumに対するpub指定

enum自体をpub指定すると、フィールドは全てpublicになる。

```rust:enum_example.rs
mod my_module {
    pub enum MyEnum {
        Elem1,
        Elem2,
    }
}

pub fn my_function {
    let elem1 = my_module::MyEnum::Elem1;
    let elem2 = my_module::MyEnum::Elem2;
}
```

### useによる名前空間の追加
```rust:use_module.rs
mod my_module {
    pub mod my_module2 {
        pub fn example_function() {};
    }
    use crate::my_module::my_module2;

    pub fn my_function() {
        my_module2::example_function();
    }
}
```

`self`キーワードを使うと相対指定できる。

```rust:use_module.rs
mod my_module {
    pub mod my_module2 {
        pub fn example_function() {};
    }
    use self::my_module::my_module2;

    pub fn my_function() {
        my_module2::example_function();
    }
}
```

### 名前空間を追加して別名をつける

asキーワードを使うと名前空間を別名で追加できる

```rust:as_keyword.rs
use std::fmt::Result;
use std::io::Result as IoResult;
```

### 名前の再エクスポート

`pub use`キーワードを使うと`use`で追加した名前空間をmoduleの外部に公開できる。

```rust:pub_use_example.rs
mod my_module{
    pub mod child_module {
        pub fn my_function() {}
    }
}

pub use crate::my_module::child_module;
```

### ネストしたuse指定

通常以下のようにuseを使うが

```rust
use std::cmp::Ordering;
use std::io;
```

中括弧によるネストを使うと以下のようになる

```rust
use std::{cmp::Ordering, io};
```

以下のように名前空間の深さが違う場合、

```rust
use std::io;
use std::io::Write;
```

`self`を使うと良い

```rust
use std::io::{self, Write};
```

### 名前空間以下の要素を全て指定する

`*`を使うと名前空間以下の要素を全て指定できる。
`*`はGlob Operatorと呼ばれる。

```rust
use std::collections::*;
```

### モジュールを別ファイルに定義して読み込む

`mod my_module;`のようにmodの宣言の後にセミコロンを置くと、Rustコンパイラはモジュール名と同名のファイルを探して読み込む。

```rust:app.rs
mod my_module;

pub use crate::my_module::child_module;

pub fn execute_function() {
    child_module::my_function()
}

```

```rust:my_module.rs
pub mod child_module {
    pub fn my_function();
}
```