> ");
// Ключевое слово `self` ссылается на область видимости текущего модуля.
// В нашем случае - модуль `my`.
// Вызов `self::function()`, так же как и вызов `function()` дают одинаковый результат,
// т.к они ссылаются на одну и ту же функцию.
self::function();
function();
// Мы так же можем использовать ключевое слово `self`,
// чтобы получить доступ к другим модулям внутри модуля `my`:
self::cool::function();
// Ключевое слово `super` ссылается на родительскую область видимости (вне модуля `my`).
super::function();
// Этим действием мы свяжем `cool::function` в области видимости *контейнера*.
// В данном случае область видимости контейнера является самой дальней областью видимости.
{
use cool::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.
extern crate
Чтобы связать контейнер с новой библиотекой, нужна декларация extern crate. Она не только свяжет библиотеку, но и импортирует все элементы в модуль с тем же именем, что и сама библиотека. Правила видимости, применимые к модулям, так же применимы и к библиотекам.
// Ссылка на `library`. Импортируем элементы, как модуль `rary`
extern crate rary;
fn main() {
rary::public_function();
// Ошибка! Функция `private_function` приватная
//rary::private_function();
rary::indirect_access();
}
# Где library.rlib путь к скомпилированной библиотеке. Предположим, что
# она находится в той же директории:
$ rustc executable.rs --extern rary=library.rlib && ./executable
вызвана `public_function()` библиотеки rary
вызвана `indirect_access()` библиотеки rary, и в ней
> вызвана `private_function()` библиотеки rary
Cargo
cargo - официальный менеджер пакетов языка Rust. В нем много функций для улучшения качества кода и увеличения скорости разработки! К ним относятся:
• Управление зависимостями и интеграция с crates.io (официальный реестр пакетов Rust)
• Осведомлённость о модульных тестах
• Осведомлённость о тестах производительности