Чуть-чуть о статье
В этой статье будет идти речь о самых основных способах использования модулей в данном языке (используемая ОС: Linux). Всем известно, что лучший способ запомнить информацию надолго — это предоставить её кому-либо в виде лекции. Для этого и была написана данная статья — чтобы помочь самому себе, но буду очень рад, если она поможет и тебе, читатель.
Корневой модуль
Давайте создадим контейнер (библиотеку) для хранения модулей (NAME — имя контейнера):
$ cargo new LNAME $ cd LNAME/
И вот что мы получили в нашем контейнере LNAME:
./ ../ Cargo.toml src/ |------ ./ |------ ../ '------ lib.rs
У всех наших модулей должен быть корневой модуль, которым является файл LNAME/src/lib.rs — он был создан автоматически. Последующие модули(суб-модули) будут «разрастаться» начитая с корневого модуля, как дерево. Мы обращаемся к суб-модулям с помощью нотации ::.В модулях мы будем хранить функции, которые возвращают строки. Пишем в файле lib.rs:
fn one() -> String {
"one".to_string() // Функция возвращает строку "one".
}
ОК. Теперь создаём новый контейнер, который будет хранить исполняемый файл(ENAME — имя контейнера для храниния исполняемого файла):
$ cargo new ENAME --bin $ cd EMANE
Чтобы мы могли использовать наш корневой модуль, нам необходимо в файл Cargo.toml контейнера EMANE записать:
[lib]
name = "имя_для_обращения"
С помощью этого имени мы будем обращаться к нашему корневому модулю(далее вместо имя_для_обращения будет num). Мы как бы присваиваем нашему корневому модулю имя.
Продолжаем писать:
path = "путь_к_нашему_модулю"
«путь_к_нашему_модулю» — это путь к модулю lib.rs относительно местоположения файла, который мы редактируем.
И пишем в main.rs следующее:
extern crate num; // Импортируем контейнер num для получения функции one().
fn main() {
println!("{} - 1",num::one()); // Вызываем функцию one() из модуля num.
}
И запускаем:
$ cargo run
Ошибка! Прочитав пояснение компилятора, вы можете сделать вывод, что функция one() приватна. Это значит, что мы не можем использовать её в своём main.rs, но можем использовать в lib.rs. И что нам делать? Поставим перед функцией слово pub:
pub fn one() ... // Делаем функцию публичной.
И запускаем:
$ cargo run
Выход:
one - 1
Ура! Первый шак сделан.
Всё, что стоит после num:: при вызовах функций должно быть публичным! Например:
num::newmod::oldmod::print_number() // Вызов функции print_number()
Чтобы получить доступ к функции print_number() нам необходимо сделать все модули, находящиеся перед функцией, публичными…
Модуль в модуле
Давайте добавим модуль в корневой модуль и перенесём туда нашу функцию:
pub mod number { // Если хотите пользоваться функцией one(), то не забывайте ставить pub.
pub fn one() -> String {
"one".to_string()
}
}
Как вы заметили, для того, чтобы создать суб-модуль, необходимо воспользоваться словом mod(обязательно воспользуйтесь словом pub — без него нас не добраться до функции one() ).
Далее необходимо изменить файл main.rs:
extern crate num;
fn main() {
println!("{} - 1",num::number::one()); // Вызываем функцию one() из модуля number,
// который находится в корневом модуле num.
}
И командуем:
$ cargo run
Выход:
one - 1
Ура! А теперь давайте попробуем объявить наш суб-модуль иначе. В lib.rs всё удаляем и пишем:
pub mod number;
Сохраняем. Если мы объявим модуль таким образом, то компилятор будет искать наш модуль либо в файле number.rs рядом с файлом, в котором находится такое объявление (в данном случае — src/number.rs), либо в файле mod.rs, который находится в папке number рядом с файлом, в котором находится такое объявление (в данном случае — src/number/mod.rs). При этом нам не надо заново объявлять модуль: это сделано при изначальном объявлении mod.!!!
Давайте рассмотрим оба варианта. Первый:
// Файл number.rs:
pub fn one() -> String { // Если хотите пользоваться функцией one(), то не забывайте ставить pub.
"one".to_string()
}
// Файл main.rs(ничего не меняется):
extern crate num;
fn main() {
println!("{} - 1",num::number::one()); // Вызываем функцию one() из модуля number,
// который находится в корневом модуле num.
}
Всё работает.
Второй вариант:
// Файл mod.rs:
pub fn one() -> String { // Если хотите пользоваться функцией one(), то не забывайте ставить pub.
"one".to_string()
}
Файл main.rs — ничего не меняется.
Всё работает.
Используем use
Ключевое слово use позволяет импортировать модуль в нашу локальную область видимости.
Короче, если мы напишем так:
extern crate num;
use num::number;
fn main() {
println!("{} - 1",number::one()); // Вызываем функцию one() из модуля number,
// который находится в корневом модуле num.
}
То нам не потребуется писать полный путь при вызове: num::number::one(). Также можно импортировать саму функцию:
extern crate num;
use num::number::one; // Пишем one без скобочек.
fn main() {
println!("{} - 1",one()); // Вызываем функцию one() не используя num::number::
}
Но так делать не рекомендуется, т.к может возникнуть конфликт имён.
The End. Продолжение следует...
Литература:
The Rust Reference (английский)
The Rust Programming Language (английский)
The Rust Programming Language (русский)
Cargo Guide (английский)
Автор: no_face