JavaRush /Java blogi /Random-UZ /Java-da bir nechta meros. Tarkib va merosga qarshi
DSergey_Kh
Daraja

Java-da bir nechta meros. Tarkib va merosga qarshi

Guruhda nashr etilgan

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. Java-da bir nechta meros.  Tarkibi merosga qarshi - 1Faraz qilaylik, sinf SuperClassmavhum va unda qandaydir metod e'lon qilingan. Ham beton sinflar ClassAva 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 ClassCva uni ClassAva 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 ClassAsinfda foydalanmoqchi bo'lsak-chi ? Yechim kompozitsiyadan foydalanishda yotadi. Quyida sinf usullarini va ob'ektlardan birining usulini aniqlash uchun kompozitsiyadan foydalanadigan sinf versiyasi mavjud .methodB()ClassBClassCClassCdoSomething()
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.
  1. 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 ClassCquyida 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 sinf ClassDkompilyatsiya 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.

  2. 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.

  3. Kompozitsiyaning yana bir afzalligi shundaki, u chaqiruv usullarida moslashuvchanlikni ta'minlaydi. Yuqorida keltirilgan sinfni amalga oshirishimiz ClassCoptimal 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.

  4. 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.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION