Salom! Javada
abstrakt klasslar haqida gaplashamiz.
Aynan shuning uchun ob'ekt qanday xatti-harakatni tanlashini bilmaganligi sababli, Java yaratuvchilari ko'p martalik meros olishdan voz kechdilar. Biroq, siz bilib olasiz, Java klasslari ko'plab interfeyslarni amalga oshiradi.
Nima uchun klasslar «abstrakt» deb ataladi
Sen, albatta, «abstraksiya» nima ekanligini eslaysan — buni allaqachon o'tganmiz :) Agar biroz unutsang — qo'rqma, eslab oling: bu OOP prinsipi, unga ko'ra klasslar va obyektlarni loyihalashtirishda faqat asosiy xususiyatlarni ajratib ko'rsatish va ikkinchi darajali narsalarni tashlab qo'yish kerak. Masalan, agarSchoolTeacher — maktab o'qituvchisi klassini loyihalashtirsak — «
bo'y» xususiyatiga ehtiyoj yo'q. Haqiqatan ham: o'qituvchi uchun bu xususiyat muhim emas. Ammo agar dasturda
BasketballPlayer — basketbol o'yinchisi klassini yaratsak —
bo'y asosiy xususiyatlardan biri bo'ladi. Shunday qilib,
abstrakt klass — bu kelajakdagi klasslar guruhi uchun maksimal abstrakt, juda-yu-judayam taxminiy "tayyorlov" hisoblanadi. Bu tayyorlovdan tayyor holda foydalanish mumkin emas — juda "xom". Ammo u kelajakdagi klasslar — abstrakt klass merosxo'rlariga ega bo'ladigan umumiy holat va xatti-harakatlarni tasvirlaydi.
Java abstrakt klasslari misollari
Avtolar bilan oddiy misolni ko'rib chiqaylik:
public abstract class Car {
private String model;
private String color;
private int maxSpeed;
public abstract void gas();
public abstract void brake();
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
}
Mana shunday eng oddiy abstrakt klass ko'rinadi. Ko'rganingdek, hech qanday alohida narsa yo'q :) Nima uchun bu bizga kerak bo'lishi mumkin? Avvalo, u bizga kerak bo'lgan subyekt — avtomobilni maksimal darajada abstrakt tarzda tasvirlaydi.
abstract so'zi bu yerda behuda emas. Dunyoda "shunchaki mashinalar" mavjud emas. Yuk mashinalari, poyga mashinalari, sedanlar, kupe va krossoverlar mavjud.
Bizning abstrakt klassimiz — bu shunchaki keyinchalik avtomobil klasslarini yaratish uchun ishlatiladigan "chizma".
public class Sedan extends Car {
@Override
public void gas() {
System.out.println("Sedan gaz bermoqda!");
}
@Override
public void brake() {
System.out.println("Sedan to'xtamoqda!");
}
}
Bu ko'p jihatdan meros olish haqidagi ma'ruzalarda gaplashgan narsaga o'xshaydi. Faqat bizda
Car klassi va uning metodlari abstrakt bo'lmagan edi. Ammo bunday yechimda bir qator kamchiliklar mavjud, ular abstrakt klasslarda tuzatilgan. Birinchi va eng muhimi —
abstrakt klassning ekzempyarini yaratish mumkin emas:
public class Main {
public static void main(String[] args) {
Car car = new Car(); // Xato! Car klassi abstraktdir!
}
}
Bu "g'oya" Java yaratuvchilari tomonidan maxsus ravishda amalga oshirilgan. Yana eslatma uchun:
abstrakt klass — bu kelajakdagi "normal" klasslar uchun chizma faqat. Sizga chizma ekzempyarlari kerak emas, to'g'rimi? Xo'sh, abstrakt klass ekzempyarlarini yaratish kerak emas :) Agar
Car klassi abstrakt bo'lmaganida, biz uni osongina obyektlarini yaratishimiz mumkin edi:
public class Car {
private String model;
private String color;
private int maxSpeed;
public void gas() {
// qandaydir mantiq
}
public void brake() {
// qandaydir mantiq
}
}
public class Main {
public static void main(String[] args) {
Car car = new Car(); // Hammasi yaxshi, mashina yaratildi
}
}
Endi dasturimizda qandaydir tushunarsiz mashina paydo bo'ldi — na yuk mashinasi, na poyga mashinasi, na sedan, va na umuman tushunarsiz narsadir. Xuddi "shunchaki mashina", ular tabiatda mavjud emas. Xuddi shu misolni hayvonlar bilan keltirish mumkin. Tasavvur qiling, dasturingizda
Animal — "shunchaki hayvon" obyektlari paydo bo'lgan. Uning qanday turi, qaysi oilaga mansub, qanday xususiyatlari bor — tushunarsiz. Uni dasturda ko'rish g'alati bo'lardi. Tabiatda hech qanday "shunchaki hayvonlar" mavjud emas. Faqat itlar, mushuklar, tulkilar, qo'zichoq va boshqalar. Abstrakt klasslar bizni "shunchaki obyektlar"dan xalos qiladi. Ular bizga asosiy holat va xatti-harakatlar beradi. Masalan, barcha mashinalar
model,
rang va
maximal tezlikga ega bo'lishi kerak, shuningdek,
gaz berish va
to'xtatishni bilishi kerak. Mana shu hammasi. Bu — umumiy abstrakt sxema, bundan keyin esa sen kerakli klasslarni loyihalashtirasan.
E'tibor bering: abstrakt klassdagi ikki metod ham
abstract deb belgilangan va umuman amalga oshirilmagan. Sababi shundaki: abstrakt klasslar "shunchaki mashinalar" uchun "standart xatti-harakatlarni" yaratmaydi. Ular faqat barcha mashinalar nima qila olishlari kerakligini aytadi. Ammo, agar sizga standart xatti-harakatlar kerak bo'lsa, abstrakt klassdagi metodlarni amalga oshirishingiz mumkin. Java bunga ruxsat beradi:
public abstract class Car {
private String model;
private String color;
private int maxSpeed;
public void gas() {
System.out.println("Gaz bermoqdamiz!");
}
public abstract void brake();
// geterlari va seterlari
}
public class Sedan extends Car {
@Override
public void brake() {
System.out.println("Sedan to'xtamoqda!");
}
}
public class Main {
public static void main(String[] args) {
Sedan sedan = new Sedan();
sedan.gas();
}
}
Konsoldagi chiqish natijasi:
“Gaz bermoqdamiz!” Ko'rganingizdek, biz abstrakt klassda bitta metodni amalga oshirdik, ikkinchisini esa qilmaganmiz. Natijada bizning
Sedan klassimiz xatti-harakati ikki qismga bo'lindi: agar
gas() metodini chaqirsak, u abstrakt
Car klassidan "kelib chiqadi", va biz
Sedan klassida
brake() metodini qayta belgiladik. Juda qulay va moslashuvchan bo'ldi. Ammo endi
bizning klassimiz umuman abstrakt emasmi? Axir, bizda, amalda, metodlarning yarmi amalga oshirilgan. Aslida — va bu juda muhim xususiyat —
klass abstrakt hisoblanadi, agar uning kamida bitta metodi abstrakt bo'lsa. Ikkita metoddan bittasi, mingta metodd dan bittasi — farq yo'q. Biz hatto barcha metodlarni amalga oshirib, birorta ham abstraktni qoldirmasligimiz mumkin. Abstrakt metodlarsiz abstrakt klass bo'ladi. Printsipial jihatdan, bu mumkin, va kompilyator xatolarni bermaydi, lekin buni qilish yaxshiroq emas: abstract so'zi ma'nosini yo'qotadi, va sizning dasturchi hamkasblaringiz buni ko'rib hayron bo'lishadi :/ Shu bilan birga,
agar metod abstract so'zi bilan belgilangan bo'lsa, har bir merosxo'r klass uni amalga oshirishi kerak yoki abstrakt deb e'lon qilinishi kerak. Aks holda kompilyator xato chiqaradi. Albatta, har bir klass faqat bitta abstrakt klassdan meros olishi mumkin, shu sababli, meros olish nuqtai nazaridan, abstrakt va oddiy klasslar o'rtasida hech qanday farq yo'q. Biz abstrakt klassdan meros olamizmi yoki oddiy klassdan, ota-klass faqat bitta bo'lishi mumkin.
Nima uchun Javada ko'p martalik klasslar meros olish yo'q
Biz allaqachon aytgan edik, Javada ko'p martalik meros olish yo'q, lekin nimaga ekanligini to'liq tushunmadik. Keling, buni hozir tushunib olaylik. Masala shundaki, agar Javada ko'p martalik meros olish mavjud bo'lsa, qiz klasslar o'zlariga qanday xatti-harakatni tanlashini bilolmay qoladi. Misol uchun, bizda ikkita klass mavjud —Toster va
NuclearBomb:
public class Toster {
public void on() {
System.out.println("Toster yoqilgan, tost qovurilmoqda!");
}
public void off() {
System.out.println("Toster o'chirildi!");
}
}
public class NuclearBomb {
public void on() {
System.out.println("Portlash!");
}
}
Ko'rganingizdek, ikkala klassda
on() metodi bor. Toster holatida u tost pishirishni boshlaydi, va yadroviy bomba holatida — portlashni amalga oshiradi. Voy :/ Endi tasavvur qiling, siz ularning orasida biror narsani yaratishga qaror qildingiz (nima sababdan ekanini bilmayman!). Va mana sizning klassingiz —
MysteriousDevice! Bu kod, albatta, ishlamaydigan va shunchaki "bu qanday bo'lishi mumkin edi" qabilidagi misol sifatida keltirilgan:
public class MysteriousDevice extends Toster, NuclearBomb {
public static void main(String[] args) {
MysteriousDevice mysteriousDevice = new MysteriousDevice();
mysteriousDevice.on(); // Bu yerda nima sodir bo'lishi kerak? Tost olamizmi yoki yadroviy apokalipsis?
}
}
Keling, nima olishimizni ko'rib chiqamiz. Sirli qurilma bir vaqtning o'zida ham Toster, ham Yadroviy Bomba hisoblanadi. Ikkalasida ham
on() metodi mavjud, natijada
MysteriousDevice obyektidan qaysi
on() metod ishlatilishi kerakligini tushunib bo'lmaydi. Obyekt buni hech qanday tushuna olmaydi. Va tortning ustiga vişna: Yadroviy Bombada
off() metodi yo'q, shuning uchun agar biz noto'g'ri topsaq, qurilmani o'chirish mumkin bo'lmaydi.
Aynan shuning uchun ob'ekt qanday xatti-harakatni tanlashini bilmaganligi sababli, Java yaratuvchilari ko'p martalik meros olishdan voz kechdilar. Biroq, siz bilib olasiz, Java klasslari ko'plab interfeyslarni amalga oshiradi.
GO TO FULL VERSION