Szukaj…


Składnia

  • mod nazwa modowa ; // Wyszukaj moduł w modname .rs lub modname /mod.rs w tym samym katalogu
  • mod nazwa modowa { blok }

Drzewo modułów

Akta:

- example.rs (root of our modules tree, generally named lib.rs or main.rs when using Cargo)
- first.rs
- second/
  - mod.rs
  - sub.rs

Moduły:

- 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 moduł musi zostać zadeklarowany w pliku example.rs , ponieważ jego rodzicem jest example a nie, na przykład, first dlatego nie można go zadeklarować w pliku first.rs lub innym pliku na tym samym poziomie katalogu

second/mod.rs

pub mod sub;

Atrybut # [ścieżka]

Za pomocą atrybutu #[path] Rdza można określić ścieżkę wyszukiwania określonego modułu, jeśli nie znajduje się on w standardowej lokalizacji. Jest to jednak zwykle odradzane , ponieważ powoduje, że hierarchia modułów jest krucha i ułatwia przerwanie kompilacji poprzez przeniesienie pliku do zupełnie innego katalogu.

#[path="../path/to/module.rs"]
mod module;

Nazwy w kodzie kontra nazwy w `use`

Składnia podwójnych dwukropków nazw w instrukcji use wygląda podobnie do nazw używanych gdzie indziej w kodzie, ale znaczenie tych ścieżek jest inne.

Nazwy w instrukcji use są domyślnie interpretowane jako bezwzględne, zaczynając od katalogu głównego skrzynki. Nazwy w innym miejscu kodu odnoszą się do bieżącego modułu.

Wyrok:

use std::fs::File;

ma to samo znaczenie w głównym pliku skrzyni, a także w modułach. Z drugiej strony, nazwa funkcji, taka jak std::fs::File::open() będzie odnosić się do standardowej biblioteki Rusta tylko w głównym pliku skrzyni, ponieważ nazwy w kodzie są interpretowane względem bieżącego modułu.

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"); 
   } 
}

Aby nazwy std::… zachowywały się wszędzie tak samo, jak w katalogu głównym skrzynki, którą można dodać:

use std;

I odwrotnie, możesz use ścieżek względnych, poprzedzając je self lub super słowami kluczowymi:

 use self::my_module::my_fn;

Dostęp do modułu nadrzędnego

Czasami przydatne może być względne importowanie funkcji i struktur bez konieczności use w projekcie projektu ścieżki absolutnej. Aby to osiągnąć, możesz użyć modułu super , tak jak:

fn x() -> u8 {
    5
}

mod example {
    use super::x;

    fn foo() {
        println!("{}", x());
    }
}

Możesz użyć super wiele razy, aby dotrzeć do „dziadka” bieżącego modułu, ale powinieneś uważać na wprowadzanie problemów z czytelnością, jeśli użyjesz super zbyt wiele razy w jednym imporcie.

Eksport i widoczność

Struktura katalogów:

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()
}

writer.rs

// This function WILL be exported.
pub fn write() {}

// This will NOT be exported.
fn open_file() {}

Podstawowa organizacja kodu

Zobaczmy, jak możemy uporządkować kod, gdy baza kodów będzie się powiększać.

01. Funkcje

fn main() {
  greet();
}

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

02. Moduły - w tym samym pliku

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. Moduły - w innym pliku w tym samym katalogu

Po przeniesieniu kodu do nowego pliku nie ma potrzeby zawijania kodu w deklaracji mod . Sam plik działa jak moduł.

// ↳ 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!");
}

Po przeniesieniu kodu do nowego pliku, jeśli kod ten został zawinięty z deklaracji mod , będzie to podmoduł pliku.

// ↳ 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. Moduły - w innym pliku w innym katalogu

Po przeniesieniu kodu do nowego pliku w innym katalogu sam katalog działa jak moduł. A mod.rs w katalogu głównym modułu jest punktem wejścia do modułu katalogu. Wszystkie inne pliki w tym katalogu działają jako podmoduł tego katalogu.

// ↳ main.rs
mod greet;

fn main() {
  greet::hello();
}
// ↳ greet/mod.rs
pub fn hello() {
  println!("Hello, world!");
}

Gdy masz wiele plików w katalogu głównym modułu,

// ↳ 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. Moduły - z self

fn main() {
  greet::call_hello();
}

mod greet {
  pub fn call_hello() { 
    self::hello();
  }

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

06. Moduły - z super

  1. Jeśli chcesz uzyskać dostęp do funkcji roota z wnętrza modułu,
fn main() {
  dash::call_hello();
}

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

mod dash {
  pub fn call_hello() {
    super::hello();
  }
}
  1. Jeśli chcesz uzyskać dostęp do funkcji w module zewnętrznym / macierzystym z wnętrza modułu zagnieżdżonego,
fn main() {
  outer::inner::call_hello();
}

mod outer {

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

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

}

07. Moduły - w use

  1. Jeśli chcesz powiązać pełną ścieżkę z nową nazwą,
use greet::hello::greet as greet_hello;

fn main() {
  greet_hello();
}

mod greet {
  pub mod hello {
    pub fn greet() {
      println!("Hello, world!");
    }
  }
}
  1. Gdy chcesz użyć zawartości zakresu skrzynek
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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow