Java-da bir nechta meros
Bir nechta meros bir nechta supersinflardan meros bo'ladigan sinf yaratishga imkon beradi. C++ kabi boshqa mashhur ob'ektga yo'naltirilgan dasturlash tillaridan farqli o'laroq, Java sinflardan bir nechta merosga ruxsat bermaydi. Java bir nechta sinf merosini qo'llab-quvvatlamaydi, chunki u olmos muammosiga olib kelishi mumkin. Va bu muammoni hal qilish yo'llarini izlash o'rniga, biz bir nechta meros kabi bir xil natijaga erishishimiz mumkin bo'lgan yaxshiroq variantlar mavjud.Olmos muammosi
Olmos muammosini osonroq tushunish uchun, keling, Java-da bir nechta meros qo'llab-quvvatlanadi deb faraz qilaylik. Bunday holda, biz quyidagi rasmda ko'rsatilganidek, sinf ierarxiyasiga ega bo'lishimiz mumkin. Faraz qilaylik, sinfSuperClass
mavhum va unda qandaydir metod e'lon qilingan. Ham beton sinflar ClassA
va ClassB
.
package com.journaldev.inheritance;
public abstract class SuperClass {
public abstract void doSomething();
}
package com.journaldev.inheritance;
public class ClassA extends SuperClass{
@Override
public void doSomething(){
System.out.println("doSomething implementation of A");
}
//ClassA own method
public void methodA(){
}
}
package com.journaldev.inheritance;
public class ClassB extends SuperClass{
@Override
public void doSomething(){
System.out.println("doSomething implementation of B");
}
//ClassB specific method
public void methodB(){
}
}
Endi biz uni amalga oshirmoqchimiz ClassC
va uni ClassA
va dan meros qilib olmoqchimiz deylik ClassB
.
package com.journaldev.inheritance;
public class ClassC extends ClassA, ClassB{
public void test(){
//calling super class method
doSomething();
}
}
E'tibor bering, usul test()
superclass usulini chaqiradi doSomething()
. Bu noaniqlikka olib keladi, chunki kompilyator qaysi superklass usulini bajarishni bilmaydi. Bu olmos muammosi deb ataladigan olmos shaklidagi sinf diagrammasi. Bu Java ko'p merosni qo'llab-quvvatlamasligining asosiy sababidir. E'tibor bering, bir nechta sinf merosi bilan bog'liq yuqoridagi muammo kamida bitta umumiy usulga ega bo'lgan uchta sinfda yuzaga kelishi mumkin.
Ko'p interfeysli meros
Java-da sinflarda bir nechta meros qo'llab-quvvatlanmaydi, lekin interfeyslarda qo'llab-quvvatlanadi. Va bitta interfeys ko'plab boshqa interfeyslarni kengaytirishi mumkin. Quyida oddiy misol keltirilgan.package com.journaldev.inheritance;
public interface InterfaceA {
public void doSomething();
}
package com.journaldev.inheritance;
public interface InterfaceB {
public void doSomething();
}
E'tibor bering, ikkala interfeys ham bir xil usulni e'lon qiladi. Endi biz quyidagi misolda ko'rsatilganidek, ikkala interfeysni kengaytiradigan interfeys yaratishimiz mumkin.
package com.journaldev.inheritance;
public interface InterfaceC extends InterfaceA, InterfaceB {
//same method is declared in InterfaceA and InterfaceB both
public void doSomething();
}
Bu juda yaxshi ishlaydi, chunki interfeyslar faqat usullarni e'lon qiladi va amalga oshirish interfeysni meros qilib olgan sinflarda amalga oshiriladi. Shunday qilib, bir nechta interfeys merosida noaniqlikni olishning hech qanday usuli yo'q.
package com.journaldev.inheritance;
public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC {
@Override
public void doSomething() {
System.out.println("doSomething implementation of concrete class");
}
public static void main(String[] args) {
InterfaceA objA = new InterfacesImpl();
InterfaceB objB = new InterfacesImpl();
InterfaceC objC = new InterfacesImpl();
//all the method calls below are going to same concrete implementation
objA.doSomething();
objB.doSomething();
objC.doSomething();
}
}
Esda tutingki, har qanday superklass usulini bekor qilganingizda yoki interfeys usulini qo'llaganingizda, izohdan foydalaning @Override
. methodA()
Agar biz sinf funksiyasidan va sinf funksiyasidan ClassA
sinfda foydalanmoqchi bo'lsak-chi ? Yechim kompozitsiyadan foydalanishda yotadi. Quyida sinf usullarini va ob'ektlardan birining usulini aniqlash uchun kompozitsiyadan foydalanadigan sinf versiyasi mavjud .methodB()
ClassB
ClassC
ClassC
doSomething()
package com.journaldev.inheritance;
public class ClassC{
ClassA objA = new ClassA();
ClassB objB = new ClassB();
public void test(){
objA.doSomething();
}
public void methodA(){
objA.methodA();
}
public void methodB(){
objB.methodB();
}
}
Tarkib va merosga qarshi
Java dasturlashning eng yaxshi amaliyotlaridan biri bu “merosdan oldin tarkibni tasdiqlash”dir. Biz ushbu yondashuvni qo'llab-quvvatlaydigan ba'zi jihatlarni ko'rib chiqamiz.-
Aytaylik, bizda superklass va uni kengaytiruvchi sinf mavjud:
package com.journaldev.inheritance; public class ClassC{ public void methodC(){ } } package com.journaldev.inheritance; public class ClassD extends ClassC{ public int test(){ return 0; } }
Yuqoridagi kod kompilyatsiya qiladi va yaxshi ishlaydi. Ammo, agar sinfning bajarilishini
ClassC
quyida ko'rsatilganidek o'zgartirsak nima bo'ladi:package com.journaldev.inheritance; public class ClassC{ public void methodC(){ } public void test(){ } }
E'tibor bering, usul
test()
subklassda allaqachon mavjud, ammo qaytarish turi boshqacha. Endi sinfClassD
kompilyatsiya qilmaydi va agar siz biron bir IDE dan foydalansangiz, u sizni supersinf yoki pastki sinfda qaytarish turini o'zgartirishni taklif qiladi.Endi bizda ko'p darajali meros ierarxiyasi mavjud bo'lgan va superklassga kirish imkoniga ega bo'lmagan vaziyatni tasavvur qiling. Kompilyatsiya xatosini olib tashlash uchun subklass usuli imzomizni yoki uning nomini o'zgartirishdan boshqa ilojimiz yo'q. Bundan tashqari, quyi sinf usulini chaqirilgan barcha joylarda o'zgartirishimiz kerak bo'ladi. Shunday qilib, meros bizning kodimizni mo'rt qiladi.
Yuqoridagi muammo kompozitsiyada hech qachon sodir bo'lmaydi va bu uni meros uchun yanada jozibador qiladi.
-
Meros bilan bog'liq yana bir muammo shundaki, biz yuqori sinfning barcha usullarini mijozga ochib beramiz va agar bizning superklassimiz to'g'ri ishlab chiqilmagan bo'lsa va xavfsizlik teshiklari mavjud bo'lsa, biz sinfimizning eng yaxshi amalga oshirilishini amalga oshirgan bo'lsak ham, biz yomon amalga oshirishga ta'sir qilamiz. supersinfdan. Tarkibi bizga superklass usullariga boshqariladigan kirishni ta'minlashda yordam beradi, meros esa superklass usullari ustidan nazoratni ta'minlamaydi. Bu ham merosdan kompozitsiyaning asosiy afzalliklaridan biridir.
-
Kompozitsiyaning yana bir afzalligi shundaki, u chaqiruv usullarida moslashuvchanlikni ta'minlaydi. Yuqorida keltirilgan sinfni amalga oshirishimiz
ClassC
optimal emas va kompilyatsiya vaqti chaqiriladigan usul bilan bog'langanligini ta'minlaydi. Minimal o'zgarishlar bilan biz usul chaqiruvini moslashuvchan va dinamik qilishimiz mumkin.package com.journaldev.inheritance; public class ClassC{ SuperClass obj = null; public ClassC(SuperClass o){ this.obj = o; } public void test(){ obj.doSomething(); } public static void main(String args[]){ ClassC obj1 = new ClassC(new ClassA()); ClassC obj2 = new ClassC(new ClassB()); obj1.test(); obj2.test(); } }
Yuqorida keltirilgan dastur natijasi:
doSomething implementation of A doSomething implementation of B
Usulni chaqirishda bunday moslashuvchanlik meros bilan mavjud emas, bu kompozitsiyani tanlashga yana bir afzallik beradi.
-
Birlik testini kompozitsiya bilan qilish osonroq, chunki biz yuqori sinfdagi barcha usullardan foydalanayotganimizni bilamiz va ularni sinov uchun nusxalashimiz mumkin. Holbuki, merosxo'rlikda biz yuqori sinfga ko'proq bog'liqmiz va superklassning barcha usullarini bilmaymiz. Shunday qilib, biz superklassning barcha usullarini sinab ko'rishimiz kerak, bu meros tufayli qo'shimcha ishdir.
Ideal holda, biz merosdan faqat pastki sinfdan yuqori sinfga munosabatlari "bo'ladi" deb belgilanganida foydalanishimiz kerak. Boshqa barcha holatlarda kompozitsiyadan foydalanish tavsiya etiladi.
GO TO FULL VERSION