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

Розділення модулів у різні файли (Separating Modules into Different Files)

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

Наприклад, давайте почнемо з коду в Лістингу 7-17, який мав кілька модулів ресторану. Ми витягнемо модулі у файли замість того, щоб усі модулі були визначені у файлі кореня крейту. У цьому випадку файл кореня крейту — це src/lib.rs, але ця процедура також працює з бінарними крейтами, чий файл кореня крейту — src/main.rs.

Спочатку ми витягнемо модуль front_of_house у його власний файл. Видаліть код усередині фігурних дужок для модуля front_of_house, залишивши лише оголошення mod front_of_house;, так щоб src/lib.rs містив код, показаний у Лістингу 7-21. Зверніть увагу, що це не скомпілюється, доки ми не створимо файл src/front_of_house.rs у Лістингу 7-22.

mod front_of_house;

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}

Далі помістіть код, що був у фігурних дужках, у новий файл із назвою src/front_of_house.rs, як показано у Лістингу 7-22. Компілятор знає, що потрібно дивитися у цей файл, тому що він натрапив на оголошення модуля в корені крейту з назвою front_of_house.

pub mod hosting {
    pub fn add_to_waitlist() {}
}

Зверніть увагу, що вам потрібно завантажити файл за допомогою оголошення mod лише один раз у вашому дереві модулів. Після того як компілятор знає, що файл є частиною проєкту (і знає, де в дереві модулів розташований код через те, де ви розмістили оператор mod), інші файли у вашому проєкті повинні посилатися на код завантаженого файлу, використовуючи шлях до того місця, де він був оголошений, як описано в розділі “Шляхи для посилання на елемент у дереві модулів”. Іншими словами, mod — це не операція “include”, яку ви могли бачити в інших мовах програмування.

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

Щоб почати переміщення hosting, ми змінюємо src/front_of_house.rs, щоб він містив лише оголошення модуля hosting:

pub mod hosting;

Потім ми створюємо каталог src/front_of_house і файл hosting.rs, щоб містився код, визначений у модулі hosting:

pub fn add_to_waitlist() {}

Якби ми натомість помістили hosting.rs у каталог src, компілятор би очікував, що код hosting.rs буде в модулі hosting, оголошеному в корені крейту, а не оголошеному як дочірній елемент модуля front_of_house. Правила компілятора щодо того, які файли перевіряти для коду яких модулів, означають, що каталоги й файли тісніше відповідають дереву модулів.

Альтернативні шляхи до файлів

Поки що ми охопили найбільш ідіоматичні шляхи до файлів, які використовує компілятор 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 (старіший стиль, шлях, що все ще підтримується)

Якщо ви використовуєте обидва стилі для одного й того самого модуля, ви отримаєте помилку компілятора. Використання змішування обох стилів для різних модулів у тому самому проєкті є дозволеним, але може бути незрозумілим для людей, які навігують вашим проєктом.

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

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

Зверніть увагу, що оператор pub use crate::front_of_house::hosting у src/lib.rs також не змінився, і use також не впливає на те, які файли компілюються як частина крейту. Ключове слово mod оголошує модулі, а Rust шукає у файлі з тим самим іменем, що й модуль, код, який потрапляє в цей модуль.

Підсумок

Rust дає змогу розділити пакет на кілька крейтів і крейт на модулі, щоб ви могли посилатися на елементи, визначені в одному модулі, з іншого модуля. Ви можете робити це, вказуючи абсолютні або відносні шляхи. Ці шляхи можна ввести в область видимості за допомогою оператора use, щоб ви могли використовувати коротший шлях для кількох використань елемента в цій області видимості. Код модуля за замовчуванням є приватним, але ви можете зробити визначення публічними, додавши ключове слово pub.

У наступному розділі ми розглянемо деякі структури даних колекцій у стандартній бібліотеці, які ви можете використовувати у вашому акуратно організованому коді.