Выбрать главу

// В нашем случае - модуль `my`.

// Вызов `self::function()`, так же как и вызов `function()` дают одинаковый результат,

// т.к они ссылаются на одну и ту же функцию.

self::function();

function();

// Мы так же можем использовать ключевое слово `self`,

// чтобы получить доступ к другим модулям внутри модуля `my`:

self::cooclass="underline" :function();

// Ключевое слово `super` ссылается на родительскую область видимости (вне модуля `my`).

super::function();

// Этим действием мы свяжем `cooclass="underline" :function` в области видимости *контейнера*.

// В данном случае область видимости контейнера является самой дальней областью видимости.

{

use cooclass="underline" :function as root_function;

root_function();

}

}

}

fn main() {

my::indirect_call();

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Модули могут быть отображены на иерархию файлов и директорий. Давайте разобьём пример с видимостью модулей на файлы:

$ tree .

.

|-- my

| |-- inaccessible.rs

| |-- mod.rs

| `-- nested.rs

`-- split.rs

В split.rs:

// Эта декларация найдёт файл с именем `my.rs` или `my/mod.rs` и вставит

// его содержимое внутрь модуля с именем `my` в этой области видимости

mod my;

fn function() {

println!("вызвана `function()`");

}

fn main() {

my::function();

function();

my::indirect_access();

my::nested::function();

}

В my/mod.rs:

// Точно так же, `mod inaccessible` и `mod nested` обнаружат файлы `nested.rs`

// и `inaccessible.rs`, и затем вставят их здесь в соответствующие модули

mod inaccessible;

pub mod nested;

pub fn function() {

println!("вызвана `my::function()`");

}

fn private_function() {

println!("вызывает `my::private_function()`");

}

pub fn indirect_access() {

print!("вызвана `my::indirect_access()`, которая\n> ");

private_function();

}

В my/nested.rs:

pub fn function() {

println!("вызвана `my::nested::function()`");

}

#[allow(dead_code)]

fn private_function() {

println!("вызвана `my::nested::private_function()`");

}

В my/inaccessible.rs:

#[allow(dead_code)]

pub fn public_function() {

println!("вызвана `my::inaccessible::public_function()`");

}

Давайте проверим, что все ещё работает, как раньше:

$ rustc split.rs && ./split

вызвана `my::function()`

вызвана `function()`

вызвана `my::indirect_access()`, которая

> вызвана `my::private_function()`

вызвана `my::nested::function()`

Контейнер (crate) — единица компиляции в языке Rust. Когда вызывается rustc some_file.rs, some_file.rs обрабатывается как файл контейнера. Если в some_file.rs есть декларация mod, то содержимое модуля будет объединено с файлом контейнера перед его компиляцией. Другими словами, модули не собираются отдельно, собираются лишь контейнеры.

Контейнер может быть скомпилирован в исполняемый файл или в библиотеку. По умолчанию, rustc создаёт из контейнера исполняемый файл. Это поведение может быть изменено добавлением флага --crate-type со значением lib к rustc.

Давайте создадим библиотеку и посмотрим, как связать её с другим контейнером.

pub fn public_function() {

println!("called rary's `public_function()`");

}

fn private_function() {

println!("called rary's `private_function()`");

}

pub fn indirect_access() {

print!("called rary's `indirect_access()`, that\n> ");

private_function();

}

$ rustc --crate-type=lib rary.rs

$ ls lib*

library.rlib

Библиотеки получают префикс «lib», и по умолчанию они получают имена в честь своего крейта, но это имя по умолчанию можно переопределить, передав параметр --crate-name в rustc или используя атрибут crate_name.