جدا کردن ماژول‌ها به فایل‌های مختلف

تا به اینجا، تمام مثال‌های این فصل چندین ماژول را در یک فایل تعریف کرده‌اند. هنگامی که ماژول‌ها بزرگ می‌شوند، ممکن است بخواهید تعریف‌های آن‌ها را به یک فایل جداگانه منتقل کنید تا کد آسان‌تر خوانده و مدیریت شود.

برای مثال، بیایید از کد موجود در لیستینگ 7-17 شروع کنیم که شامل چندین ماژول مرتبط با رستوران بود. ما این ماژول‌ها را به جای تعریف در فایل ریشه جعبه (crate)، به فایل‌های جداگانه منتقل می‌کنیم. در این مثال، فایل ریشه جعبه (crate) src/lib.rs است، اما این روش برای جعبه‌ها (crates)ی باینری که فایل ریشه آن‌ها 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 ایجاد نشود کامپایل نخواهد شد.

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: اعلان ماژول front_of_house که بدنه آن در src/front_of_house.rs خواهد بود

سپس، کدی که داخل آکولادهای ماژول front_of_house بود را به یک فایل جدید به نام src/front_of_house.rs منتقل می‌کنیم، همان‌طور که در لیستینگ 7-22 نشان داده شده است. کامپایلر می‌داند که باید این فایل را بررسی کند زیرا در فایل ریشه جعبه (crate) با نام front_of_house اعلان ماژول را دیده است.

Filename: src/front_of_house.rs
pub mod hosting {
    pub fn add_to_waitlist() {}
}
Listing 7-22: تعریف‌های داخل ماژول front_of_house در src/front_of_house.rs

توجه داشته باشید که شما فقط یک بار نیاز دارید تا یک فایل را با استفاده از دستور mod در درخت ماژول خود بارگذاری کنید. وقتی کامپایلر می‌فهمد که فایل بخشی از پروژه است (و می‌فهمد که کد در کجای درخت ماژول قرار دارد به خاطر جایی که دستور mod را قرار داده‌اید)، سایر فایل‌های پروژه شما باید با استفاده از مسیری که به محل اعلان فایل اشاره می‌کند به کد بارگذاری شده ارجاع دهند، همان‌طور که در بخش «مسیرها برای اشاره به یک آیتم در درخت ماژول» توضیح داده شد. به عبارت دیگر، mod یک عملیات “شامل کردن” (include) نیست که ممکن است در زبان‌های برنامه‌نویسی دیگر دیده باشید.

در مرحله بعد، ماژول 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;

سپس یک دایرکتوری به نام src/front_of_house و یک فایل hosting.rs ایجاد می‌کنیم تا تعریف‌هایی که در ماژول hosting انجام شده‌اند را در آن قرار دهیم:

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

اگر به جای آن فایل hosting.rs را در دایرکتوری src قرار دهیم، کامپایلر انتظار خواهد داشت که کد hosting.rs در یک ماژول hosting که در ریشه جعبه (crate) اعلان شده باشد قرار داشته باشد، نه به عنوان یک زیرماژول از ماژول front_of_house. قوانین کامپایلر برای مشخص کردن این که کدام فایل‌ها برای کدام ماژول‌ها بررسی شوند، به این معناست که دایرکتوری‌ها و فایل‌ها با درخت ماژول مطابقت بیشتری دارند.

مسیرهای فایل جایگزین

تاکنون مسیرهای فایل ایدیوماتیک را که کامپایلر Rust استفاده می‌کند پوشش داده‌ایم، اما Rust از یک سبک قدیمی‌تر از مسیر فایل نیز پشتیبانی می‌کند. برای یک ماژول به نام front_of_house که در ریشه جعبه (crate) اعلان شده است، کامپایلر کد ماژول را در مکان‌های زیر جستجو می‌کند:

  • 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 هیچ تأثیری بر اینکه چه فایل‌هایی به عنوان بخشی از جعبه (crate) کامپایل شوند ندارد. کلمه کلیدی mod ماژول‌ها را اعلان می‌کند و Rust در فایلی با همان نام ماژول به دنبال کدی می‌گردد که وارد آن ماژول شود.

خلاصه

Rust به شما اجازه می‌دهد یک بسته را به چندین جعبه (crate) و یک جعبه (crate) را به ماژول‌ها تقسیم کنید تا بتوانید به آیتم‌هایی که در یک ماژول تعریف شده‌اند از ماژول دیگری ارجاع دهید. می‌توانید این کار را با مشخص کردن مسیرهای مطلق یا نسبی انجام دهید. این مسیرها می‌توانند با یک دستور use به محدوده وارد شوند تا بتوانید از یک مسیر کوتاه‌تر برای استفاده‌های متعدد از آن آیتم در آن محدوده استفاده کنید. کد ماژول به صورت پیش‌فرض خصوصی است، اما می‌توانید با افزودن کلمه کلیدی pub تعریف‌ها را عمومی کنید.

در فصل بعدی، به برخی از ساختارهای داده‌ای مجموعه در کتابخانه استاندارد خواهیم پرداخت که می‌توانید در کد مرتب و سازماندهی‌شده خود از آن‌ها استفاده کنید.