— Men senga «kirish modifikatorlari» haqida gapirib beraman. Bir vaqtlar men ularni senga aytib berganman, ammo takrorlash – bilimning onasi.
Sening klass o'zgaruvchilaring va metodlaring boshqa klasslardan kirishini (ko'rinishini) boshqarishing mumkin. Kirish modifikatori "Qaysi metodga/qaysi o'zgaruvchiga kim murojaat qila oladi?" degan savolga javob beradi. Har bir metod yoki o'zgaruvchiga faqat bitta modifikator belgilash mumkin.
1) «public» modifikatori.
public modifikatori bilan belgilangan o'zgaruvchi, metod yoki klassga dasturdagi istalgan joydan murojaat qilish mumkin. Bu eng yuqori darajada ochiqlik – hech qanday cheklovlar yo'q.
2) «private» modifikatori.
private modifikatori bilan belgilangan o'zgaruvchi, metod yoki klassga faqat o'sha klassning o'zidan murojaat qilinishi mumkin. Barcha boshqa klasslar uchun belgilangan metod yoki o'zgaruvchi – ko'rinmas. Bu eng yuqori darajada yopiqlik – faqat o'z klassi. Bunday metodlar meros qilib olinmaydi va qayta yozilmaydi. Ularga o'rnidan kirish ham mumkin emas.
3) «Modifikator «defolt».
Agar o'zgaruvchi yoki metod hech qaysi modifikator bilan belgilangan bo'lmasa, demak, ular «defolt modifikatori» bilan belgilangan hisoblanadi. Bunday modifikator bilan o'zgaruvchilar va metodlar, ular belgilangan paketin barcha klasslari uchun ko'rinadi va faqat ularga. Bu modifikatorni "package" yoki "package private" deb ham atashadi, ya'ni kirish paketin barcha klasslariga ochilgan.
4) «protected» modifikatori.
Bu kirish darajasi biroz kengroq, package dan. protected modifikatori bilan belgilangan o'zgaruvchi, metod yoki klassga uning o'z paketi (package kabi) va undan meros olgan barcha klasslardan kirish mumkin.
Izoh bilan jadval:
| Ko'rinish turi | Kalit so'z | Kirish | |||
|---|---|---|---|---|---|
| O'z klassi | O'z paketi | Klass — meros oluvchi | Barcha klasslar | ||
| Yopiq | private | Bor | Yo'q | Yo'q | Yo'q |
| Packet | (modifikator yo'q) | Bor | Bor | Yo'q | Yo'q |
| Himoyalangan | protected | Bor | Bor | Bor | Yo'q |
| Ochiq | public | Bor | Bor | Bor | Bor |
Bu jadvalni oson eslab qolish usuli bor. O'zingizdan xuddi bir vasiyatnoma tuzib, barcha narsalarni to'rt toifaga ajratayotganingizni tasavvur qiling. Kim sizning narsalaringizdan foydalanishi mumkin?
| Kim kirishi mumkin | Modifikator | Misol |
|---|---|---|
| Faqat o'zim | private | Shaxsiy kundalik |
| Oila | (modifikator yo'q) | Oilaviy suratlar |
| Oila va meros oluvchilar | protected | Oilaviy mulk |
| Hammaga | public | Xotiralar |
— Va agar bir oilani bir paketda joylashgan klasslar deb tasavvur qilsa, juda ham o'xshash.
— Shuningdek, senga metodlarni qayta yozish bo'yicha bir nechta qiziqarli narsalarni aytmoqchiman.
1) Abstrakt metodni noaniq amalga oshirish.
Faraz qilamiz, senga kod bor:
class Cat
{
public String getName()
{
return "Vaska";
}
}
Va sen undan Tiger klassini meros qilib olayotganda yangi klassga interfeys qo'shmoqchi bo'lding
class Cat
{
public String getName()
{
return "Vaska";
}
}
interface HasName
{
String getName();
int getWeight();
}
class Tiger extends Cat implements HasName
{
public int getWeight()
{
return 115;
}
}
Agar sen faqat Intellij IDEA tomonidan ko'rsatilgan barcha mavjud metodlarni amalga oshirsang, keyin xatoni uzoq qidirib topishing mumkin.
Ma'lum bo'ldiki, Tiger klassida Catdan olingan getName metodi mavjud va u HasName interfeysi uchun getName metodi deb hisoblanadi.
— Men buni qo'rqinchli deb bilmayman.
— Bu yaxshi emas, bu ko'proq xato qilish uchun potentsial joy.
Lekin undan ham yomon bo'lishi mumkin:
interface HasWeight
{
int getValue();
}
interface HasSize
{
int getValue();
}
class Tiger extends Cat implements HasWeight, HasSize
{
public int getValue()
{
return 115;
}
}
Ma'lum bo'ldiki, sen har doim bir nechta interfeysdan meros ololmaysan. To'g'ri, meros olish mumkin, lekin ularni to'g'ri amalga oshirish – yo'q. Misolga qarang, ikkala interfeys ham sen getValue() metodini amalga oshirishingni talab qilmoqda va nima qaytarishi kerakligi aniq emas: vaznmi (weight) yoki o'lchammi (size). Bu juda noqulay narsa, agar sen bunga duch kelsang.
— Ha, rozi bo'ldim. Metodni amalga oshirmoqchisan, lekin mumkin emas. Birdan sen allaqachon bazaviy klassdan shunday nomdagi metodni meros qilib olding. Buzildi.
— Lekin yaxshi xabarlar bor.
2) Ko'rinishning kengayishi. Metodni qayta yozishda ko'rinishni kengaytirishga ruxsat beriladi. Mana bu qanday ko'rinishda:
| Java kod | Ta'rif |
|---|---|
|
|
|
Biz metodning ko'rinishini protected dan public gacha kengaytirdik. |
| Qo'llanilishi | Nega bu "qonuniy" |
|---|---|
|
Hammasi yaxshi. Bu yerda biz hatto metod ko'rinishi meros oluvchi klassda kengaytirilganini bilmaymiz. |
|
Bu yerda ko'rinishni kengaytirilgan metod chaqiriladi. Agar bu mumkin bo'lmasa, har doim Tiger'da metodni e'lon qilishingiz mumkin edi: Ya'ni hech qanday xavfsizlikni buzish haqida gap yo'q. |
|
Agar barcha shartlar bazaviy turdagi metodni (Cat) chaqirish uchun mos keladigan bo'lsa, ular albatta meros oluvchi turini chaqirish uchun mos keladi (Tiger). Metod chaqiruviga cheklovlar kuchaytirilmadi, aksincha yumshatildi. |
— To'liq tushundim, deb ishonch hosil qilmayman, lekin buni amalga oshirish mumkinligini eslab qolaman.
3) Natija turini toraytirish.
Qayta yozilgan metodda biz natija turini toraytirishimiz mumkin.
| Java kod | Ta'rif |
|---|---|
|
|
|
Biz getMyParent metodini qayta yozdik, endi u Tiger turidagi ob'ektni qaytaradi. |
| Qo'llanilishi | Nega bu "qonuniy" |
|---|---|
|
Hammasi yaxshi. Bu yerda biz hatto meros oluvchi klassda getMyParent metodining natija turi toraytirilganini bilmaymiz. "Eski kod" nima qilsa, shunday ishlaydi. |
|
Bu yerda natija turi toraytirilgan metod chaqiriladi. Agar buni amalga oshirish imkoni bo'lmasa, har doim Tiger'da metodni e'lon qilishingiz mumkin edi: Ya'ni hech qanday xavfsizlikni buzish va/yoki turga mos kelmaslik haqida gap yo'q. |
|
Bu yerda ham hammasi yaxshi ishlaydi, garchi biz o'zgaruvchilar turini bazaviy klassga (Cat) kengaytirdik. Hech qanday muammo yo'q getMyParent metodi chaqirilganda, chunki uning natijasi, garchi Tiger klassiga tegishli bo'lsa ham, hali ham myParent bazaviy klass (Cat) o'zgaruvchisi uchun yaxshi tayinlanishi mumkin. Tiger ob'ektlarini Tiger klassida ham, Cat klassida ham o'zgaruvchilarda saqlash mumkin. |
— Ha. Men tushundim. Metodlarni qayta yozishda, bizning ob'ektlarimizni faqat bazaviy klass bilan ishlay oladigan kodga topshirganimizda, hammasi qanday ishlashini o'ylashimiz kerak.
— Aynan shunday! Shunday qilib, savol: nima uchun metodni qayta yozishda natija turini kengaytira olmaysiz?
— Bu aniq, keyin bazaviy klassdagi kod ishlamaydi:
| Java kod | Muammo izohi |
|---|---|
|
|
|
Biz getMyParent metodini qayta yozdik va natija turini kengaytirdik. Bu yerda hammasi yaxshi. |
|
O'shanda bizning bu kod ishlamay qoladi. getMyParent metodi chaqirilishi mumkin, chunki u aslida Tiger tipidagi ob'ektda chaqirilmoqda. Va biz tayinlashdan oldin hech qanday tekshirishga ega emasmiz. Demak, myParent tipidagi Cat o'zgaruvchisi satr uchun havola saqlashi mumkin bo'lish ehtimoli bor. |
— Ajoyib misol, Amigo!
Java-da metod chaqirishdan oldin, ob'ektda bunday metod bor yoki yo'qligi tekshirilmaydi. Barcha tekshiruvlar bajarilayotgan vaqtida sodir bo'ladi. Va [gipotezikal] mavjud bo'lmagan metod chaqirishi ehtimoli bor, dastur kodini mavjud bo'lmagan joyda bajarishga olib keladi. Bu, oxir-oqibat, fojiali xatoga olib keladi va operatsion tizim dasturni majburiy yakuni qiladi.
— Bu qiziq. Bilaman.
GO TO FULL VERSION