— Salom, Amigo!
— Yana salomlashyapmizmi, Elliy!
— Xo‘p, xolang bilan tortishma. 31-asrda qabul qilingan qayta salomlashish, agar odamni yarim soatdan ortiq ko‘rmasangiz. Shunday ekan, xafa bo‘lma!
Yana bir qiziqarli mavzu – robotlarni ko‘payishi!
— O_O.
— Hazillashyapman, yangi mavzu – anonim ichki sinflar.
Ba'zida Java-da shunday vaziyat paydo bo‘ladi-ki, sinfni bir nechta sinfdan meros olish kerak bo'ladi. Java'da sinflarning ko‘p meros olishiga yo‘l qo'yilmaganligi sababli, bu muammoni ichki sinflar yordamida hal qilishadi: kerakli sinfda biz ichki sinfni e'lon qilamiz va undan kerakli sinfni meros olamiz. Misol:
class Tiger extends Cat
{
public void tigerRun()
{
.....
}
public void startTiger()
{
TigerThread thread = new TigerThread();
thread.start();
}
class TigerThread extends Thread
{
public void run()
{
tigerRun();
}
}
}
Keling, ushbu misolni ko‘rib chiqamiz:
Thread sinfidan meros olish kerak, shunda run metodini qayta yozamiz.
Buning uchun Tiger sinfi ichida ichki sinf TigerThreadni e'lon qildik, uni Thread dan meros oldik va unda run metodini qayta yozdik.
Bizning qulayligimiz uchun Tiger sinfi ichida ikkita metodni e'lon qildik (Thread sinfning run va start metodlari analogi) – metodlar tigerRun va startTiger.
StartTiger metodida biz TigerThread turidagi ob'ektni yaratamiz va unda start() metodini chaqiramiz.
Java-mashina yangi ipni yaratadi va bu ip TigerThread sinfidagi run metodini chaqirishdan boshlaydi.
Va bu metod o‘z navbatida bizning run metodimizni chaqiradi – metod tigerRun.
– Men iplar bilan allaqachon ishlayapman, shuning uchun bu juda murakkab emasdek tuyuladi.
Metodlarni albatta tigerRun va startTiger deb nomlash kerakmi?
— Yo‘q, biz ularni run va start deb nomlashimiz mumkin edi, lekin men Thread dan meros olmayotganimizni qo‘shimcha ravishda ko‘rsatmoqchi edim, shuningdek men tushuntirishlarimda adashib ketishingiz mumkin edi.
— Ok. Shunda hammasi tushunarli. Faqat startTiger metodini ikkinchi marta chaqirishda biz yana bir Thread sinfini yaratamiz va uni ishga tushiramiz. Natijada bizda "bitta yo'lbars ikki xil ipda yugurib yuradi" degan holat yuzaga kelmayaptimi?
— Juda ko‘zchilik qildingiz. To‘g‘ri, bu yaxshi emas. Unda keling kodni shunday yozamiz:
class Tiger extends Cat
{
public void tigerRun()
{
.....
}
public void startTiger()
{
thread.start();
}
private TigerThread thread = new TigerThread();
private class TigerThread extends Thread
{
public void run()
{
tigerRun();
}
}
}
— Juda zo‘r emas. Baribir bunday metodni ikki marta chaqirish mumkin emas. Lekin bu safar biz hech bo‘lmaganda ikkinchi ipni yaratmaydigan va hammasi yaxshi ekanligini ko‘rsatadigan ko‘rsatma qilmaslikka harakat qilamiz.
— To‘g‘ri, ikkinchi marta ishga tushirdi, yo‘lbars – Exception olasiz.
— Men allaqachon sizdan ko‘ra yaxshiroq xatolarni ko‘rayapman, Elliy!
Ha, siz yaxshi ish qildingiz. Shunday qilib, anonim ichki sinflarga o‘tamiz.
Yuqoridagi kodda bir nechta jihatlarga e'tibor bering:
1) Biz Thread sinfidan meros oldik, lekin asosan unga hech qanday kod qo‘shmadik. Biz meros olishimiz kerak edi, Thread sinfini kengaytirish maqsadida "meros olish" kerak edi.
2) Faqat bitta TigerThread sinfi ob'ekti yaratiladi.
Ya'ni, bitta metodni qayta yozish va bitta ob'ektni yaratish uchun biz bir qancha kod yozdik.
Konstruktorlarning paydo bo‘lishini aytganimni eslaysizmi?
| Kashf qilinishidan oldin | Kashf qilinishidan keyin |
|---|---|
|
|
— Ko‘ramanki, kod yanada ixcham bo‘ldi, lekin nima bo‘lganini aniq tushunmayman.
— Biz to‘rtta narsani bir joyda birlashtirishimiz mumkin:
1) meros oluvchi sinfni e’lon qilish
2) metodni qayta yozish
3) o‘zgaruvchini e’lon qilish
4) meros oluvchi sinfni ob’ektini yaratish.
Aslida biz ikkitookim birlashtiramiz – meros oluvchi sinfni e'lon qilish va uning ob'ektini yaratish:
| Anonim sinfsiz | Anonim sinf bilan |
|---|---|
|
|
Sintaksisni yana bir ko‘rib chiqamiz:
Thread thread = new Thread();
Thread thread = new Thread()
{
};
E’tibor bering — biz yangi sinfni e’lon qilibgina qolmaymiz — biz o‘zgaruvchini yaratamiz — oxirida nuqta-vergul qo‘yiladi!
— Va agar biz run metodini qayta yozishni xohlasak, buni shunday yozishimiz kerak:
Thread thread = new Thread()
{
public void run()
{
System.out.println("new run-method");
}
};
— Tezda qo‘l ushlab qoldingiz – yaxshi!
— Rahmat. Va agar menga Thread sinfida mavjud bo‘lmagan boshqa metodlar kerak bo‘lsa-chi?
— Ularni qo‘shishingiz mumkin.
Bu ham to‘liq ichki sinf, garchi anonim:
| Java kodi | Tavsif |
|---|---|
|
Qizil rangda o‘zgaruvchini yaratish kodi ko‘rsatilgan. Yashil – ob’ekt yaratish. Ko‘k – anonim sinf-meros oluvchi kodi. |
— To‘liq ichki sinf?
Ya'ni, men tashqi sinfning o‘zgaruvchilaridan foydalanishim mumkinmi?
— Ha, albatta mumkin.
— Va agar men konstruktoriga biror narsa yuborsam bo‘ladimi?
— Ha, lekin faqat asosiy sinf konstruktorining parametrlariga:
| Sinf | Anonim ichki sinf ob’ekti |
|---|---|
|
|
Biz begona konstruktoriga o‘z parametrlarimizni qo‘sha olmaymiz. Ammo biz tashqi sinfning o‘zgaruvchilaridan foydalanishimiz mumkin - bu kamchilikni sezilarli darajada qoplaydi.
— Va agar men baribir konstruktoriga qo‘shimcha parametrlar qo‘shishim juda zarur bo‘lsa-chi?
— Unda odatiy anonim bo‘lmagan ichki sinfni e'lon qiling va undan foydalaning.
— Haqiqatan ham, men buni esdan chiqardim.
Agar men statik o‘zgaruvchini e'lon qilsam-chi, u holda anonim sinf ichki emas, balki ichkaridagi sinf bo‘ladi — ya'ni, tashqi sinfga havolasiz?
— Yo‘q. U aynan anonim ichki sinf bo‘ladi. Misollarni ko‘ring:
| Anonim sinf bilan | Anonim sinfsiz |
|---|---|
|
|
|
|
— Aniq. Faqat o‘zgaruvchini statik qilish mumkin, lekin sinfni emas.
— Ha.
Aslida, kompilyatsiya jarayonida Kompilyator barcha anonim ichki sinflar uchun ichki sinflarni yaratadi. Bunday sinflar odatda "1", "2", "3" va hokazo nomlarini olishadi.
GO TO FULL VERSION