جدا کردن ماژولها به فایلهای مختلف
تا به اینجا، تمام مثالهای این فصل چندین ماژول را در یک فایل تعریف کردهاند. هنگامی که ماژولها بزرگ میشوند، ممکن است بخواهید تعریفهای آنها را به یک فایل جداگانه منتقل کنید تا کد آسانتر خوانده و مدیریت شود.
برای مثال، بیایید از کد موجود در لیستینگ 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 ایجاد نشود کامپایل نخواهد شد.
mod front_of_house;
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
front_of_house
که بدنه آن در src/front_of_house.rs خواهد بودسپس، کدی که داخل آکولادهای ماژول front_of_house
بود را به یک فایل جدید به نام src/front_of_house.rs منتقل میکنیم، همانطور که در لیستینگ 7-22 نشان داده شده است. کامپایلر میداند که باید این فایل را بررسی کند زیرا در فایل ریشه جعبه (crate) با نام front_of_house
اعلان ماژول را دیده است.
pub mod hosting {
pub fn add_to_waitlist() {}
}
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
باشد:
pub mod hosting;
سپس یک دایرکتوری به نام src/front_of_house و یک فایل hosting.rs ایجاد میکنیم تا تعریفهایی که در ماژول hosting
انجام شدهاند را در آن قرار دهیم:
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
تعریفها را عمومی کنید.
در فصل بعدی، به برخی از ساختارهای دادهای مجموعه در کتابخانه استاندارد خواهیم پرداخت که میتوانید در کد مرتب و سازماندهیشده خود از آنها استفاده کنید.