Определение модулей для контроля видимости и конфиденциальности
В этом разделе мы поговорим о модулях и других частях системы модулей, а именно: путях(paths), которые позволяют именовать элементы; ключевом слове use
, которое приносит путь в область видимости; ключевом слове pub
, которое делает элементы общедоступными. Мы также обсудим ключевое слово as
, внешние пакеты и оператор glob. А пока давайте сосредоточимся на модулях!
Модули позволяют организовывать код внутри крейта по группам для удобства чтения и простого повторного использования. Модули также контролируют конфиденциальность (privacy) элементов: определяют может элемент использоваться внешним кодом, быть публичным (public) или является деталями внутренней реализации и недоступен для внешнего использования, т.е. является приватным (private).
В качестве примера, давайте напишем библиотечный крейт предоставляющий функциональность ресторана. Мы определим сигнатуры функций, но оставим их тела пустыми, чтобы сосредоточиться на организации кода, вместо реализации кода для ресторана.
В ресторанной индустрии некоторые части ресторана называются фронтом дома, а другие задней частью дома. Фронт дома это там где находятся клиенты; здесь размещаются места клиентов, официанты принимают заказы и оплаты, а бармены делают напитки. Задняя часть дома это где шеф-повара и повара работают на кухне, моют посудомоечные машины, а менеджеры занимаются административной работой.
Чтобы структурировать крейт аналогично тому, как работает настоящий ресторан, можно организовать размещение функций во вложенных модулях. Создадим новую библиотеку (библиотечный крейт) с именем restaurant
выполнив команду cargo new --lib restaurant
; затем вставим код из листинга 7-1 в файл src/lib.rs для определения некоторых модулей и сигнатур функций.
Файл: src/lib.rs
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
fn seat_at_table() {}
}
mod serving {
fn take_order() {}
fn serve_order() {}
fn take_payment() {}
}
}
Листинг 7-1. Модуль front_of_house
содержащий другие модули, которые затем содержат функции
Мы определяем модуль, начиная с ключевого слова mod
, затем определяем название модуля (в данном случае front_of_house
) и размещаем фигурные скобки вокруг тела модуля. Внутри модулей, можно иметь другие модули, как в случае с модулями hosting
и serving
. Модули также могут содержать определения для других элементов, таких как структуры, перечисления, константы, типажи или - как в листинге 7-1 - функции.
Используя модули, мы можем сгруппировать связанные определения вместе и сказать почему они являются связанными. Программистам, использующим такой код, будет легче найти определения, которые они хотели использовать, потому что они могли бы ориентироваться в сгруппированном коде, вместо того, чтобы прочитать все определения. Программисты, добавляющие новые функции в этот код, будут знать, где разместить код для поддержания порядка в программе.
Как мы упоминали ранее, файлы src/main.rs и src/lib.rs называются корнями крейтов. Причина такого именования в том, что любой из этих двух файлов определяет содержимое и размещает в корне структуры модуля, известной как дерево модулей, корневой модуль известный как crate
.
В листинге 7-2 показано дерево модулей для структуры модулей приведённой в коде листинга 7-1.
crate
└── front_of_house
├── hosting
│ ├── add_to_waitlist
│ └── seat_at_table
└── serving
├── take_order
├── serve_order
└── take_payment
Листинг 7-2: Дерево модулей для для структуры модулей приведённой в коде в листинге 7-1
Это дерево показывает, как некоторые из модулей вкладываются друг в друга (например, hosting
находится внутри front_of_house
). Дерево также показывает, что некоторые модули являются братьями (siblings) друг для друга, то есть они определены в одном модуле (hosting
и serving
- братья которые определены внутри front_of_house
). Продолжая метафору с семьёй, то, если модуль A содержится внутри модуля B, мы говорим, что модуль A является потомком (child) модуля B, а модуль B является родителем (parent) модуля A. Обратите внимание, что корнем (отцом, главным предком) всего дерева модулей является неявный модуль с именем crate
.
Дерево модулей может напомнить вам дерево каталогов файловой системы на компьютере; это очень удачное сравнение! По аналогии с каталогами в файловой системе, мы используется модули для организации кода. И так же, как нам надо искать файлы в каталогах на компьютере, нам требуется способ поиска нужных модулей.