Поиск…


Синтаксис

  • mod modname ; // Поиск модуля в modname .rs или modname /mod.rs в том же каталоге
  • mod modname { block }

Дерево модулей

файлы:

- 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 , а не, например, first и , таким образом , не может быть объявлен в first.rs или другой файл в каталоге того же уровень

second/mod.rs

pub mod sub;

Атрибут # [путь]

Атрибут 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::… имена вести себя везде так же, как в корневом ящике, вы можете добавить:

use std;

И наоборот, вы можете use пути use относительно префикса их с помощью self или super keywords:

 use self::my_module::my_fn;

Доступ к родительскому модулю

Иногда бывает полезно импортировать функции и структуры относительно без необходимости use что-то с его абсолютным путем в вашем проекте. Для этого вы можете использовать модуль super , например:

fn x() -> u8 {
    5
}

mod example {
    use super::x;

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

Вы можете использовать super несколько раз , чтобы достичь «прародителя» вашего текущего модуля, но вы должны быть осторожны с введением проблем читаемости , если вы используете 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()
}

writer.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