サーチ…


構文

  • 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

  1. モジュールの内部からルート関数にアクセスするには、
fn main() {
  dash::call_hello();
}

fn hello() {
  println!("Hello, world!");
}

mod dash {
  pub fn call_hello() {
    super::hello();
  }
}
  1. ネストしたモジュールの内部から外部/親モジュールの関数にアクセスする場合は、
fn main() {
  outer::inner::call_hello();
}

mod outer {

  pub fn hello() {
    println!("Hello, world!");
  }

  mod inner {
    pub fn call_hello() {
      super::hello();
    }
  }

}

07.モジュール - use

  1. フルパスを新しい名前にバインドする場合は、
use greet::hello::greet as greet_hello;

fn main() {
  greet_hello();
}

mod greet {
  pub mod hello {
    pub fn greet() {
      println!("Hello, world!");
    }
  }
}
  1. クレートスコープレベルのコンテンツを使用する場合
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();
  }
}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow