Modul daraxtidagi elementga murojaat qilish yo'llari
Rust-ga modul daraxtidagi elementni qayerdan topish mumkinligini ko'rsatish uchun biz fayl tizimida harakat qilishda qanday yo'l(path) ishlatgan bo'lsak, xuddi shunday yo'ldan foydalanamiz. Funksiyani chaqirish uchun biz uning yo'lini bilishimiz kerak.
Yo'l ikki shaklda bo'lishi mumkin:
- Absolyut yo'l - bu crate ildizidan boshlanadigan to'liq yo'l; tashqi cretedagi kod uchun mutlaq yo'l crate nomidan boshlanadi va joriy cratedagi kod uchun esa
crate
bilan boshlanadi.. - N isbiy yo‘l joriy moduldan boshlanadi va joriy modulda
self
,super
yoki identifikatordan foydalanadi.
Mutlaq va nisbiy yo‘llardan keyin ikki nuqta (::
) bilan ajratilgan bir yoki bir nechta identifikatorlar keladi.
7-1 ro'yxatiga qaytsak, biz navbat_listiga_qoshish
funksiyasini chaqirmoqchimiz deylik.
Bu so'rash bilan bir xil: navbat_listiga_qoshish
funksiyasining yo'li nima?
7-3 ro'yxatda 7-1 ro'yxati mavjud bo'lib, ba'zi modullar va funksiyalar olib tashlangan.
Biz crate ildizida belgilangan yangi restoranda_ovqatlanish
funksiyasidan navbat_listiga_qoshish
funksiyasini chaqirishning ikkita usulini ko‘rsatamiz. Bu yoʻllar toʻgʻri, ammo bu misolni avvalgidek tuzishga toʻsqinlik qiladigan yana bir muammo bor. Sababini birozdan keyin tushuntiramiz.
restoranda_ovqatlanish
funksiyasi kutubxonamizning public API-ning bir qismidir, shuning uchun biz uni pub
kalit so'zi bilan belgilaymiz. “pub
kalit so'zi bilan yo'llarni ochish” bo‘limida biz pub
haqida batafsilroq to‘xtalib o'tamiz.
Fayl nomi: src/lib.rs
mod uyning_oldi {
mod xizmat {
fn navbat_listiga_qoshish() {}
}
}
pub fn restoranda_ovqatlanish() {
// Mutlaq yo'l (Absolute path)
crate::uyning_oldi::xizmat::navbat_listiga_qoshish();
// Nisbiy yo'l (Relative path)
uyning_oldi::xizmat::navbat_listiga_qoshish();
}
Biz birinchi marta restoranda_ovqatlanish
ichida navbat_listiga_qoshish
funksiyasini chaqirganimizda mutlaq yo'ldan foydalanamiz. navbat_listiga_qoshish
funksiyasi restoranda_ovqatlanish
bilan bir xil crateda belgilangan, ya'ni mutlaq yoʻlni boshlash uchun crate
kalit soʻzidan foydalanishimiz mumkin. Keyin biz navbat_listiga_qoshish
ga o'tgunimizcha ketma-ket modullarning har birini o'z ichiga olamiz. Siz bir xil strukturaga ega fayl tizimini tasavvur qilishingiz mumkin: biz navbat_listiga_qoshish
dasturini ishga tushirish uchun /uyning_oldi/xizmat/navbat_listiga_qoshish
yo'lini belgilaymiz; crate ildizidan boshlash uchun crate
nomidan foydalanish shelldagi fayl tizimi ildizidan boshlash uchun /
dan foydalanishga o'xshaydi.
Biz restoranda_ovqatlanish
ichida navbat_listiga_qoshish
ni ikkinchi marta chaqirganimizda nisbiy yo'ldan foydalanamiz. Yo'l uyning_oldi
bilan boshlanadi, modul nomi restoranda_ovqatlanish
bilan bir xil modul daraxti darajasida belgilangan. Bu yerda fayl tizimi ekvivalenti uyning_oldi/xizmat/navbat_listiga_qoshish
yo'lidan foydalaniladi. Modul nomi bilan boshlash yo'l nisbiy ekanligini bildiradi.
Nisbiy yoki mutlaq yo‘ldan foydalanishni tanlash loyihangiz asosida qabul qilinadigan qaror bo‘lib, element definitioni kodini elementdan foydalanadigan koddan alohida yoki birga ko‘chirish ehtimoli ko‘proq ekanligiga bog‘liq.
Masalan, uyning_oldi
moduli va restoranda_ovqatlanish
funksiyasini mijoz_tajribasi
nomli modulga o‘tkazsak, mutlaq yo‘lni navbat_listiga_qoshish
ga yangilashimiz kerak bo‘ladi, lekin nisbiy yo‘l baribir amal qiladi.
Biroq, agar biz restoranda_ovqatlanish
funksiyasini ovqatlanish
nomli modulga alohida ko'chirsak, restoranda_ovqatlanish
chaqiruvining mutlaq yo'li bir xil bo'lib qoladi, lekin nisbiy yo'l yangilanishi kerak bo'ladi. Umuman olganda, bizning afzal ko'rganimiz mutlaq yo'llarni belgilashdir, chunki biz kod definitionlari va element chaqiruvlarini bir-biridan mustaqil ravishda ko'chirishni xohlaymiz.
Keling, 7-3 ro'yxatini kompilatsiya qilishga harakat qilaylik va nima uchun u hali kompilatsiya bo'lmaganligini bilib olaylik! Biz olgan xato 7-4 ro'yxatda ko'rsatilgan.
$ cargo build
Compiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0603]: module `xizmat` is private
--> src/lib.rs:9:28
|
9 | crate::uyning_oldi::xizmat::navbat_listiga_qoshish();
| ^^^^^^^ private module
|
note: the module `xizmat` is defined here
--> src/lib.rs:2:5
|
2 | mod xizmat {
| ^^^^^^^^^^^
error[E0603]: module `xizmat` is private
--> src/lib.rs:12:21
|
12 | uyning_oldi::xizmat::navbat_listiga_qoshish();
| ^^^^^^^ private module
|
note: the module `xizmat` is defined here
--> src/lib.rs:2:5
|
2 | mod xizmat {
| ^^^^^^^^^^^
For more information about this error, try `rustc --explain E0603`.
error: could not compile `restaurant` due to 2 previous errors
Xato xabarlari xizmat
moduli private ekanligini aytadi. Boshqacha qilib aytadigan bo'lsak, bizda xizmat
moduli va navbat_listiga_qoshish
funksiyasi uchun to'g'ri yo'llar mavjud, ammo Rust ulardan foydalanishimizga ruxsat bermaydi, chunki u private bo'limlarga kirish imkoniga ega emas. Rust-da barcha elementlar (funktsiyalar, metodlar, structlar, enumlar, modullar va konstantalar) standart bo'yicha ota-modullar uchun privatedir. Agar siz funksiya yoki struktura kabi elementni yaratmoqchi bo'lsangiz, uni modulga joylashtirasiz.
Ota-moduldagi elementlar ichki modullar ichidagi private elementlardan foydalana olmaydi, lekin bolalar modullaridagi elementlar o'zlarining ota-modullaridagi elementlardan foydalanishi mumkin. Buning sababi shundaki, bolalar modullari o'zlarining amalga oshirish tafsilotlarini o'rab oladi va yashiradi, lekin bolalar modullari ular aniqlangan kontekstni ko'rishlari mumkin. Bizning metaforamizni davom ettirish uchun, maxfiylik qoidalarini restoranning orqa ofisi kabi tasavvur qiling: u erda nima sodir bo'layotgani restoran mijozlari uchun private, ammo ofis menejerlari o'zlari ishlayotgan restoranda hamma narsani ko'rishlari va qilishlari mumkin.
Rust modul tizimining shu tarzda ishlashini tanladi, shuning uchun ichki dastur tafsilotlarini yashirish standart bo'yichadir. Shunday qilib, siz ichki kodning qaysi qismlarini tashqi kodni buzmasdan o'zgartirishingiz mumkinligini bilasiz. Biroq, Rust sizga obyektni hammaga ochiq qilish uchun pub
kalit so'zidan foydalanib, tashqi ajdod modullariga ichki modullar kodining ichki qismlarini ochish imkoniyatini beradi.
pub
kalit so'zi bilan yo'llarni ochish
Keling, 7-4 ro'yxatdagi xatoga qaytaylik, bu bizga xizmat
moduli private ekanligini aytdi. Biz ota-moduldagi restoranda_ovqatlanish
funksiyasi bolalar modulidagi navbat_listiga_qoshish
funksiyasiga kirishini xohlaymiz, shuning uchun biz xizmat
modulini pub
kalit so'zi bilan belgilaymiz, ro'yxat 7-5da ko`rsatilganidek.
Fayl nomi: src/lib.rs
mod uyning_oldi {
pub mod xizmat {
fn navbat_listiga_qoshish() {}
}
}
pub fn restoranda_ovqatlanish() {
// Mutlaq yo'l (Absolute path)
crate::uyning_oldi::xizmat::navbat_listiga_qoshish();
// Nisbiy yo'l (Relative path)
uyning_oldi::xizmat::navbat_listiga_qoshish();
}
Afsuski, 7-5 ro'yxatdagi kod hali ham 7-6 ro'yxatda ko'rsatilganidek xatolikka olib keladi.
$ cargo build
Compiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0603]: function `navbat_listiga_qoshish` is private
--> src/lib.rs:9:37
|
9 | crate::uyning_oldi::xizmat::navbat_listiga_qoshish();
| ^^^^^^^^^^^^^^^ private function
|
note: the function `navbat_listiga_qoshish` is defined here
--> src/lib.rs:3:9
|
3 | fn navbat_listiga_qoshish() {}
| ^^^^^^^^^^^^^^^^^^^^
error[E0603]: function `navbat_listiga_qoshish` is private
--> src/lib.rs:12:30
|
12 | uyning_oldi::xizmat::navbat_listiga_qoshish();
| ^^^^^^^^^^^^^^^ private function
|
note: the function `navbat_listiga_qoshish` is defined here
--> src/lib.rs:3:9
|
3 | fn navbat_listiga_qoshish() {}
| ^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0603`.
error: could not compile `restaurant` due to 2 previous errors
Nima bo'ldi? mod xizmat
oldiga pub
kalit so‘zini qo‘shish modulni hammaga ochiq qiladi. Ushbu o'zgarish bilan, agar biz uyning_oldi
ga kira olsak, biz xizmat
ga kira olamiz. Lekin xizmat
ning tarkibi hamon private; modulni public qilish uning mazmunini ochiq qilmaydi. Moduldagi pub
kalit so‘zi faqat uning ota-modullaridagi kodni unga murojaat qilish imkonini beradi, uning ichki kodiga kirishga ruxsat bermaydi.
Modullar konteyner bo'lgani uchun modulni faqat public qilish orqali biz ko'p narsa qila olmaymiz; biz oldinga borishimiz va modul ichidagi bir yoki bir nechta narsalarni ham hammaga ochiq qilishni tanlashimiz kerak.
7-6 roʻyxatdagi xatolar navbat_listiga_qoshish
funksiyasi private ekanligini bildiradi.
Maxfiylik qoidalari structlar, enumlar, funksiyalar va metodlar hamda modullarga nisbatan qo'llaniladi.
7-7 ro'yxatda ko'rsatilganidek, definitiondan oldin pub
kalit so'zini qo'shish orqali navbat_listiga_qoshish
funksiyasini ham hammaga ochiq qilaylik.
Fayl nomi: src/lib.rs
mod uyning_oldi {
pub mod xizmat {
pub fn navbat_listiga_qoshish() {}
}
}
pub fn restoranda_ovqatlanish() {
// Mutlaq yo'l (Absolute path)
crate::uyning_oldi::xizmat::navbat_listiga_qoshish();
// Nisbiy yo'l (Relative path)
uyning_oldi::xizmat::navbat_listiga_qoshish();
}
Endi kod kompilyatsiya qilinadi! Nima uchunpub
kalit soʻzini qoʻshish ushbu yoʻllardan navbat_listiga_qoshish
da maxfiylik qoidalariga nisbatan foydalanish imkonini berishini bilish uchun mutlaq va nisbiy yoʻllarni koʻrib chiqamiz.
Mutlaq yo'lda biz crate modul daraxtining ildizi bo'lgan crate
dan boshlaymiz. uyning_oldi
moduli crate ildizida belgilangan. uyning_oldi
ochiq boʻlmasa-da, restoranda_ovqatlanish
funksiyasi uyning_oldi
bilan bir xil modulda aniqlanganligi sababli (yaʼni, restoranda_ovqatlanish
va uyning_oldi
siblingdir ya'ni aka-uka), biz restoranda_ovqatlanish
dan uyning_oldi
ga murojaat qilishimiz mumkin. Keyingi o'rinda pub
bilan belgilangan xizmat
moduli. Biz xizmat
ning ota-moduliga kira olamiz, shuning uchun biz xizmat
ga kira olamiz. Nihoyat, navbat_listiga_qoshish
funksiyasi pub
bilan belgilangan va biz uning asosiy moduliga kira olamiz, shuning uchun bu funksiya chaqiruvi ishlaydi!
Nisbiy yo'lda mantiq birinchi qadamdan tashqari mutlaq yo'l bilan bir xil bo'ladi: yo'l crate ildizidan emas, uyning_oldi
dan boshlanadi. uyning_oldi
moduli restoranda_ovqatlanish
bilan bir xil modul ichida aniqlanadi, shuning uchun restoranda_ovqatlanish
belgilangan moduldan boshlanadigan nisbiy yo‘l ishlaydi. Keyin, xizmat
va navbat_listiga_qoshish
pub
bilan belgilanganligi sababli, qolgan yo‘l ishlaydi va bu funksiya chaqiruvi amal qiladi!
Agar siz kutubxona crateyingizni boshqa loyihalar sizning kodingizdan foydalanishi uchun baham ko'rishni rejalashtirmoqchi bo'lsangiz, public API sizning crateyingiz foydalanuvchilari bilan tuzilgan shartnoma bo'lib, ular sizning kodingiz bilan qanday aloqada bo'lishini belgilaydi. Odamlar sizning crateyingizga bog'liq bo'lishini osonlashtirish uchun public API-ga o'zgartirishlarni boshqarish bo'yicha ko'plab fikrlar mavjud. Bu mulohazalar ushbu kitob doirasidan tashqarida; agar sizni ushbu mavzu qiziqtirsa, Rust API ko'rsatmalariga qarang.
Binary va kutubxonaga ega paketlar uchun eng yaxshi amaliyotlar
Paketda src/main.rs binary crate ildizi ham, src/lib.rs kutubxona cratesi ildizi ham bo‘lishi mumkinligini aytib o'tdik va ikkala crate ham standart bo‘yicha paket nomiga ega bo‘ladi. Odatda, kutubxona va binary crateni o'z ichiga olgan ushbu patternli paketlar kutubxona cratesi bilan kod chaqiradigan bajariladigan faylni ishga tushirish uchun binary crateda yetarli kodga ega bo'ladi. Bu boshqa loyihalarga paket taqdim etadigan eng ko'p funksiyalardan foydalanish imkonini beradi, chunki kutubxona cratesi kodi public bo'lishi mumkin.
Modul daraxti src/lib.rs da aniqlanishi kerak. Keyin har qanday public obyektlar binary crateda paket nomi bilan yo'llarni boshlash orqali ishlatilishi mumkin. Binary crate kutubxona cratesidan foydalanuvchiga aylanadi, xuddi butunlay tashqi crate kutubxona cratesidan foydalanadi: u faqat pulic APIdan foydalanishi mumkin. Bu sizga yaxshi API yaratishga yordam beradi; Siz nafaqat muallif, balki mijoz hamsiz!
12-bobda biz ushbu tashkiliy amaliyotni binary crate va kutubxona cratesini o'z ichiga olgan buyruq qatori dasturi bilan ko'rsatamiz.
Nisbiy yo'llarni super
bilan boshlash
Yo'l boshida super
dan foydalanib, joriy modul yoki crate ildizi emas, balki ota-modulda boshlanadigan nisbiy yo'llarni qurishimiz mumkin. Bu fayl tizimi yoʻlini ..
sintaksisi bilan boshlashga oʻxshaydi. super
dan foydalanish bizga ota-modulda ekanligini biladigan elementga murojaat qilish imkonini beradi, bu modul ota-ona bilan chambarchas bog'liq bo'lsa, modul daraxtini qayta tartibga solishni osonlashtiradi, lekin ota-ona bir kun kelib modul daraxtining boshqa joyiga ko'chirilishi mumkin.
7-8 ro'yxatdagi kodni ko'rib chiqing, unda oshpaz noto'g'ri buyurtmani tuzatgan va uni mijozga shaxsan yetkazgan vaziyatni modellashtiradi. uyning_orqasi
modulida aniqlangan buyurtmani_tuzatish
funksiyasi super
bilan boshlanadigan yetkazib_berish
yo‘lini belgilash orqali asosiy modulda belgilangan yetkazib_berish
funksiyasini chaqiradi:
Fayl nomi: src/lib.rs
fn yetkazib_berish() {}
mod uyning_orqasi {
fn buyurtmani_tuzatish() {
oshpaz();
super::yetkazib_berish();
}
fn oshpaz() {}
}
buyurtmani_tuzatish
funksiyasi uyning_orqasi
modulida joylashgan, shuning uchun biz super
dan uyning_orqasi
ota-moduliga o'tishimiz mumkin. U yerdan yetkazib_berish
ni qidiramiz va uni topamiz.
Muvaffaqiyat! Bizning fikrimizcha, uyning_orqasi
moduli va yetkazib_berish
funksiyasi bir-biri bilan bir xil munosabatda bo'lib qoladi va agar biz cratening modul daraxtini qayta tashkil etishga qaror qilsak, birgalikda harakatlanadi. Shu sababli, biz super
dan foydalandik, shuning uchun kelajakda bu kod boshqa modulga ko‘chirilsa, kodni yangilash uchun kamroq joylarga ega bo‘lamiz.
Structlar va Enumlarni public qilish
Shuningdek, structlar va enumlarni public sifatida belgilash uchun pub
dan foydalanishimiz mumkin, ammo pub
dan structlar va enumlar bilan foydalanish uchun qo'shimcha tafsilotlar mavjud. Agar struct definitiondan oldin pub
dan foydalansak, biz structni hammaga public qilamiz, lekin structning maydonlari hali ham private bo'lib qoladi. Biz har bir sohani alohida-alohida public qilishimiz yoki qilmasligimiz mumkin. 7-9 roʻyxatda biz public qizdirilgan_non
maydoni, lekin private mavsumiy_meva
maydoni bilan public uyning_orqasi:: nonushta
structini belgilab oldik. Bu restoranda mijoz ovqat bilan birga keladigan non turini tanlashi mumkin bo'lgan holatni modellashtiradi, ammo oshpaz qaysi meva mavsumda va omborda borligiga qarab ovqatga hamroh bo'lishini hal qiladi. Mavjud mevalar tezda o'zgaradi, shuning uchun mijozlar mevani tanlay olmaydi yoki hatto qaysi mevani olishini ko'ra olmaydi.
Fayl nomi: src/lib.rs
mod uyning_orqasi {
pub struct Nonushta {
pub yopilgan_non: String,
mavsumiy_meva: String,
}
impl Nonushta {
pub fn yoz(yopilgan_non: &str) -> Nonushta {
Nonushta {
yopilgan_non: String::from(yopilgan_non),
mavsumiy_meva: String::from("shaftoli"),
}
}
}
}
pub fn restoranda_ovqatlanish() {
// Yozda javdar yopilgan noni bilan nonushta buyurtma qiling
let mut ovqat = uyning_orqasi::Nonushta::yoz("Javdar");
// Qaysi nonni xohlashimiz haqidagi fikrimizni o'zgartiring
ovqat.yopilgan_non = String::from("Bug'doy");
println!("Iltimos, {}li yopilgan nonni istayman", ovqat.yopilgan_non);
// Agar izohni olib tashlasak, keyingi qator kompilyatsiya qilinmaydi;
// ovqat bilan birga keladigan mavsumiy mevalarni ko'rish yoki
// o'zgartirishga ruxsat berilmagan
// ovqat.mavsumiy_meva = String::from("ko'katlar");
}
uyning_orqasi::Nonushta
structdagi yopilgan_non
maydoni public bo'lgani uchun restoranda_ovqatlanish
da biz yopilgan_non
maydoniga nuqta belgisi yordamida yozishimiz va o'qishimiz mumkin. Esda tutingki, biz mavsumiy_meva
maydonidan restoranda_ovqatlanish
da foydalana olmaymiz, chunki mavsumiy_meva
privatedir. Qaysi xatoga yo'l qo'yganingizni bilish uchun mavsumiy_meva
maydoni qiymatini o'zgartiruvchi qatorni izohdan chiqarib ko'ring!
Shuni ham yodda tutingki, uyning_orqasi::Nonushta
private maydonga ega bo'lgani uchun struct Nonushta
misolini yaratuvchi public bog'langan funksiyani ta'minlashi kerak (biz uni bu yerda yoz
deb nomladik).Agar Nonushta
bunday funksiyaga ega boʻlmagan boʻlsa, biz restoranda_ovqatlanish
da Nonushta
misolini yarata olmadik, chunki biz restoranda_ovqatlanish
da private mavsumiy_meva
maydonining qiymatini oʻrnata olmadik.
Aksincha, agar biz enumni public qilsak, uning barcha variantlari public bo'ladi. 7 10 roʻyxatda koʻrsatilganidek, bizga faqat enum
kalit soʻzidan oldin pub
kerak boʻladi.
Fayl nomi: src/lib.rs
mod uyning_orqasi {
pub enum Taom {
Palov,
Salat,
}
}
pub fn restoranda_ovqatlanish() {
let buyurtma1 = uyning_orqasi::Taom::Palov;
let buyurtma2 = uyning_orqasi::Taom::Salat;
}
Biz Taom
ro‘yxatini hammaga public qilganimiz uchun restoranda_ovqatlanish
da Palov
va Salat
variantlaridan foydalanishimiz mumkin.
Enumlar, agar ularning variantlari public bo'lmasa, unchalik foydali emas; Har bir holatda pub
bilan barcha enum variantlariga izoh qo'yish zerikarli bo'lar edi, shuning uchun enum variantlari uchun standart umumiy bo'lishi kerak. Structlar ko'pincha maydonlari public bo'lmasdan foydali bo'ladi, shuning uchun struct maydonlari, agar pub
bilan izohlanmagan bo'lsa, standart bo'yicha hamma narsa private bo'lishining umumiy qoidasiga amal qiladi.
pub
bilan bog'liq yana bir holat bor, biz uni ko'rib chiqmaganmiz va bu bizning modul tizimining oxirgi xususiyati: use
kalit so'zi. Biz avval use
ni o'z ichiga olamiz, so'ngra pub
va use
ni qanday birlashtirishni ko'rsatamiz.