Поиск…
Синтаксис
- 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
- Когда вы хотите получить доступ к корневой функции изнутри модуля,
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();
}
}