Har bir yangi Java versiyasining oʻziga xos farqi bor. Mana oʻrganilgan materialdagi oʻzgarishlardan bir misol: Java 5 dan oldin tilida enumlar yo'q edi.
Agar interfacelar haqida gaplashayotgan bo'lsak, bir yangilikni ko'rib chiqamiz — interfacelarda default methodlar.
Sen allaqachon bilasan, interfeys xatti-harakatni amalga oshirmaydi. Uning vazifasi – uni implement qiladigan barcha obyektlar qanday xatti-harakatga ega bo'lishi kerakligini tavsiflash.
Lekin dasturchilar ko'pincha barcha klasslarda bir xil bo'lgan biror metodni implement qilish zarurati bilan duch kelishgan.
Bizning eski avtomobillar misolini ko'rib chiqaylik:
public interface Car {
public void gas();
public void brake();
}
public class Sedan implements Car {
@Override
public void gas() {
System.out.println("Gaz!");
}
@Override
public void brake() {
System.out.println("Tormoz!");
}
}
public class Truck implements Car {
@Override
public void gas() {
System.out.println("Gaz!");
}
@Override
public void brake() {
System.out.println("Tormoz!");
}
}
public class F1Car implements Car {
@Override
public void gas() {
System.out.println("Gaz!");
}
@Override
public void brake() {
System.out.println("Tormoz!");
}
}
Seningcha, bu kodning asosiy muammosi nimada?
Sen albatta payqading, biz bir xil kodni ko'p yozdik! Bu dasturlashda keng tarqalgan muammo, uni oldini olish kerak.
Java 8 chiqqunga qadar bu muammoni hal qilishning maxsus varianti yo'q edi. Bu versiya chiqqandan so'ng, default metodlarni belgilash va ularni interfeys ichida amalga oshirish mumkin bo'ldi!
Mana qanday qilib bu amalga oshiriladi:
public interface Car {
public default void gas() {
System.out.println("Gaz!");
}
public default void brake() {
System.out.println("Tormoz!");
}
}
public class Sedan implements Car {
}
public class Truck implements Car {
}
public class F1Car implements Car {
}
Endi gas() va brake() metodlari, barcha mashinalar uchun bir xil bo'lgan, interfeysga kiritilgan, va takrorlangan kod kerak emas. Shu bilan birga, metodlar har bir klassda mavjud!
public class Main {
public static void main(String[] args) {
F1Car f1Car = new F1Car();
Sedan sedan = new Sedan();
Truck truck = new Truck();
truck.gas();
sedan.gas();
f1Car.brake();
}
}
Agar 100 ta classda gas() metodi bo'lsa-yu, lekin ulardan faqat 99 tasi bir xil xatti-harakatga ega bo'lsa-chi? Bu barcha narsani buzadimi va default metod bu holatda mos kelmaydimi?
Albatta, yo'q :) Interfeyslarning default metodlarini qayta aniqlash mumkin.
public class UnusualCar implements Car {
@Override
public void gas() {
System.out.println("Bu mashina boshqacha gaz beradi!");
}
@Override
public void brake() {
System.out.println("Bu mashina boshqacha tormoz beradi!");
}
}
Boshqa 99 turdagi mashinalar default metodni amalga oshiradi va UnusualCar klassi — istisno — umumiy holatni buzmaydi va o'z xatti-harakatini belgilashda davom etadi.
Interfeyslarda Ko'p Miras Olish
Sen allaqachon bilasan, Java da ko'p miras olish yo'q. Buning sabablarini batafsil alohida ma'ruzalarda ko'rib chiqamiz.
Boshqa tillarda, masalan, C++ da aslida mavjud. Ko'p miras olmaslik bilan bir ob'ektda bir qator turli xil xususiyatlar va "xatti-harakatlar" bo'lishi mumkinligi muammosiga duch kelamiz.
Hayotiy misol: ota-onalar uchun biz — farzandmiz, o'qituvchilar uchun — talabamiz, shifokorlar uchun — bemormiz. Hayotda biz turli rollarda namoyon bo'lamiz va shu bilan birga, har xil xatti-harakat qilamiz: o'qituvchilar bilan albatta yaqin do'stlar bilan gaplashgandek gaplashmaymiz.
Bu holatni kodga ko'chirishga harakat qilamiz. Bizda ikki klass bor deb tasavvur qilaylik: Pond va Aviary. Ko'lmak uchun suzuvchi qushlar kerak, aviary uchun esa uchuvchi qushlar kerak.
Buning uchun biz ikki asosiy klass yaratdik — FlyingBird va Waterfowl.
public class Waterfowl {
}
public class FlyingBird {
}
Shunday qilib, aviaryga FlyingBirddan meros olgan qushlarni, ko'lmakka esa Waterfowldan meros olganlarni yuboramiz.
Hammasi sodda qilib ko'rsatilgan.
Lekin agar biror o'rdakni qayerga aniqlash kerak bo'lsa, nima qilamiz?
U ham uchadi, ham suzadi. Va bizda ko'p meros olish yo'q.
Yaxshiyamki, Java da interfeyslarning ko'p realizatsiyasi mavjud. Agar klass bir nechta ota-onani meros qilib ololmasa, bir nechta interfeyslarni amalga oshirishi mumkin!
Bizning o'rdak ham uchuvchi, ham suzuvchi bo'lishi mumkin :) Yaxshi natijaga erishish uchun FlyingBird va Waterfowlni klass o'rniga interfeys qilish kifoya.
public class Duck implements FlyingBird, Waterfowl {
//har ikki interfeysning metodlari bitta klassda osongina birlashadi
@Override
public void fly() {
System.out.println("Uchamiz!");
}
@Override
public void swim() {
System.out.println("Suzamiz!");
}
}
Shu tufayli bizning dasturimiz klasslarni moslashuvchan boshqarishni saqlab qoladi va default metodlarni amalga oshirish bilan birga ob'ektlarning xatti-harakatini belgilash imkoniyatimiz deyarli cheksiz bo'ladi! :)
GO TO FULL VERSION