Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Размещение модулей в разных файлах

До сих пор все примеры в этой главе определяли несколько модулей в одном файле. Когда модули становятся большими, вы можете захотеть переместить их определения в отдельные файлы, чтобы упростить навигацию по коду.

Для начала, давайте рассмотрим код Листинга 7-17, в котором было несколько модулей ресторана. Мы будем извлекать модули в файлы вместо того, чтобы определять все модули в файле корня крейта. В нашем случае, корень крейта — это src/lib.rs, но это разделение также работает и с бинарными крейтами, у которых корнем крейта будет src/main.rs.

First, we’ll extract the front_of_house module to its own file. Remove the code inside the curly brackets for the front_of_house module, leaving only the mod front_of_house; declaration, so that src/lib.rs contains the code shown in Listing 7-21. Note that this won’t compile until we create the src/front_of_house.rs file in Listing 7-22.

Filename: src/lib.rs
mod front_of_house;

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}
Listing 7-21: Declaring the front_of_house module whose body will be in src/front_of_house.rs

Затем поместим код, который был в фигурных скобках, в новый файл с именем src/front_of_house.rs, как показано в Листинге 7-22. Компилятор знает, что нужно искать в этом файле, потому что он наткнулся в корневом модуле крейта на объявление модуля с именем front_of_house.

Filename: src/front_of_house.rs
pub mod hosting {
    pub fn add_to_waitlist() {}
}
Listing 7-22: Definitions inside the front_of_house module in src/front_of_house.rs

Обратите внимание, что вам нужно только один раз загрузить файл с помощью объявления mod в вашем дереве модулей. Как только компилятор узнает, что файл является частью проекта (и узнает, где в дереве модулей находится код из-за того, куда вы поместили инструкцию mod), другие файлы в вашем проекте должны ссылаться на код загруженного файла, используя путь к месту, где он был объявлен, как описано в разделе “Пути для ссылки на элемент в дереве модулей”. Другими словами, mod — это не операция “подключения”, которую вы могли видеть в других языках программирования.

Далее мы извлечём модуль hosting в его собственный файл. Процесс немного отличается, потому что hosting является дочерним модулем для front_of_house, а не корня крейта. Мы поместим файл для hosting в новый каталог, который будет назван по имени его предка в дереве модулей (в данном случае — src/front_of_house/).

Чтобы начать перенос hosting, мы поменяем src/front_of_house.rs так, чтобы он содержал только объявление модуля hosting:

Filename: src/front_of_house.rs
pub mod hosting;

Then, we create a src/front_of_house directory and a hosting.rs file to contain the definitions made in the hosting module:

Filename: src/front_of_house/hosting.rs
pub fn add_to_waitlist() {}

If we instead put hosting.rs in the src directory, the compiler would expect the hosting.rs code to be in a hosting module declared in the crate root and not declared as a child of the front_of_house module. The compiler’s rules for which files to check for which modules’ code mean the directories and files more closely match the module tree.

Альтернативные пути к файлам

До сих пор мы рассматривали наиболее идиоматические пути к файлам, используемые компилятором Rust, но Rust также поддерживает и старый стиль пути к файлу. Для модуля с именем front_of_house, объявленного в корне крейта, компилятор будет искать код модуля в:

  • src/front_of_house.rs (современный стиль; использовался нами до сих пор)
  • src/front_of_house/mod.rs (старый стиль; всё ещё поддерживается)

Для модуля с именем hosting, который является подмодулем front_of_house, компилятор будет искать код модуля в:

  • src/front_of_house/hosting.rs (современный стиль; использовался нами до сих пор)
  • src/front_of_house/hosting/mod.rs (старый стиль; всё ещё поддерживается)

If you use both styles for the same module, you’ll get a compiler error. Using a mix of both styles for different modules in the same project is allowed but might be confusing for people navigating your project.

Основным недостатком стиля, в котором используются файлы с именами mod.rs, является то, что в вашем проекте может оказаться много файлов с именами mod.rs, что может привести к путанице, если вы одновременно откроете их в редакторе.

Мы перенесли код каждого модуля в отдельный файл, а дерево модулей осталось прежним. Вызовы функций в eat_at_restaurant будут работать без каких-либо изменений, несмотря на то, что определения находятся в разных файлах. Этот метод позволяет перемещать модули в новые файлы по мере их разрастания.

Обратите внимание, что инструкция pub use crate::front_of_house::hosting в src/lib.rs также не изменилась, и use не влияет на то, какие файлы компилируются как часть крейта. Ключевое слово mod объявляет модули, и Rust ищет код, который входит в этот модуль, в файле с тем же именем, что и у модуля.

Подведём итоги

Rust lets you split a package into multiple crates and a crate into modules so that you can refer to items defined in one module from another module. You can do this by specifying absolute or relative paths. These paths can be brought into scope with a use statement so that you can use a shorter path for multiple uses of the item in that scope. Module code is private by default, but you can make definitions public by adding the pub keyword.

В следующей главе мы рассмотрим некоторые коллекции данных из стандартной библиотеки, которые вы можете использовать в своём (хорошо теперь организованном) коде.