JavaRush /Blog Java /Random-MS /Warisan berbilang di Jawa. Komposisi lwn Warisan

Warisan berbilang di Jawa. Komposisi lwn Warisan

Diterbitkan dalam kumpulan

Pewarisan Berbilang di Jawa

Pewarisan berbilang membolehkan anda mencipta kelas yang mewarisi daripada berbilang kelas super. Tidak seperti beberapa bahasa pengaturcaraan berorientasikan objek popular lain, seperti C++, Java tidak membenarkan pewarisan berbilang daripada kelas. Java tidak menyokong warisan kelas berbilang kerana ia boleh membawa kepada masalah berlian. Dan bukannya mencari cara untuk menyelesaikan masalah ini, terdapat pilihan yang lebih baik bagaimana kita boleh mencapai hasil yang sama seperti warisan berbilang.

Masalah berlian

Untuk memahami masalah berlian dengan lebih mudah, mari kita anggap bahawa warisan berbilang disokong di Jawa. Dalam kes ini, kita boleh mempunyai hierarki kelas seperti yang ditunjukkan dalam imej di bawah. Warisan berbilang di Jawa.  Komposisi lwn. Warisan - 1Mari kita anggap bahawa kelas SuperClassadalah abstrak dan beberapa kaedah diisytiharkan di dalamnya. Kedua-dua kelas konkrit ClassAdan 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(){
	}
}
Sekarang andaikan kita mahu melaksanakan ClassCdan mewarisinya daripada ClassAdan ClassB.
package com.journaldev.inheritance;
public class ClassC extends ClassA, ClassB{
	public void test(){
		//calling super class method
		doSomething();
	}
}
Ambil perhatian bahawa kaedah test()memanggil kaedah superclass doSomething(). Ini membawa kepada kekaburan kerana pengkompil tidak tahu kaedah superclass untuk dilaksanakan. Ini adalah gambar rajah kelas berbentuk berlian yang dipanggil masalah berlian. Inilah sebab utama mengapa Java tidak menyokong pelbagai warisan. Ambil perhatian bahawa masalah di atas dengan warisan kelas berbilang hanya boleh berlaku dengan tiga kelas yang mempunyai sekurang-kurangnya satu kaedah biasa.

Warisan Pelbagai Antara Muka

Di Java, warisan berbilang tidak disokong dalam kelas, tetapi ia disokong dalam antara muka. Dan satu antara muka boleh memanjangkan banyak antara muka lain. Di bawah adalah contoh mudah.
package com.journaldev.inheritance;
public interface InterfaceA {
	public void doSomething();
}
package com.journaldev.inheritance;
public interface InterfaceB {
	public void doSomething();
}
Ambil perhatian bahawa kedua-dua antara muka mengisytiharkan kaedah yang sama. Sekarang kita boleh mencipta antara muka yang memanjangkan kedua-dua antara muka ini, seperti yang ditunjukkan dalam contoh di bawah.
package com.journaldev.inheritance;
public interface InterfaceC extends InterfaceA, InterfaceB {
	//same method is declared in InterfaceA and InterfaceB both
	public void doSomething();
}
Ini berfungsi dengan baik kerana antara muka hanya mengisytiharkan kaedah dan pelaksanaan akan dilakukan dalam kelas yang mewarisi antara muka. Oleh itu, tidak ada cara untuk mendapatkan kekaburan dalam warisan antara muka berbilang.
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();
	}
}
Sila ambil perhatian bahawa apabila anda mengatasi mana-mana kaedah superclass atau melaksanakan kaedah antara muka, gunakan anotasi @Override. Bagaimana jika kita ingin menggunakan fungsi methodA()kelas ClassAdan fungsi methodB()kelas ClassBdalam kelas ClassC? Penyelesaiannya terletak pada penggunaan komposisi. Di bawah ialah versi kelas ClassCyang menggunakan komposisi untuk menentukan kedua-dua kaedah kelas dan kaedah doSomething()salah satu objek.
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();
	}
}

Komposisi lwn Warisan

Salah satu amalan pengaturcaraan Java terbaik ialah "meluluskan komposisi sebelum pewarisan." Kami akan meneroka beberapa aspek yang menyokong pendekatan ini.
  1. Katakan kita mempunyai superclass dan kelas yang memanjangkannya:

    package com.journaldev.inheritance;
    public class ClassC{
    	public void methodC(){
    	}
    }
    package com.journaldev.inheritance;
    public class ClassD extends ClassC{
    	public int test(){
    		return 0;
    	}
    }

    Kod di atas disusun dan berfungsi dengan baik. Tetapi, bagaimana jika kita menukar pelaksanaan kelas ClassCseperti yang ditunjukkan di bawah:

    package com.journaldev.inheritance;
    public class ClassC{
    	public void methodC(){
    	}
    	public void test(){
    	}
    }

    Ambil perhatian bahawa kaedah test()sudah wujud dalam subkelas, tetapi jenis pulangan adalah berbeza. Sekarang kelas ClassDtidak akan menyusun dan jika anda menggunakan mana-mana IDE, ia akan menggesa anda untuk menukar jenis pulangan dalam superclass atau subclass.

    Sekarang bayangkan situasi di mana kita mempunyai hierarki warisan kelas berbilang peringkat dan tidak mempunyai akses kepada superclass. Kami tidak mempunyai pilihan selain menukar tandatangan kaedah subkelas kami atau namanya untuk mengalih keluar ralat kompilasi. Kami juga perlu menukar kaedah subkelas di semua tempat di mana ia dipanggil. Oleh itu, warisan menjadikan kod kami rapuh.

    Masalah di atas tidak akan berlaku dengan komposisi dan ini menjadikannya lebih menarik untuk diwarisi.

  2. Satu lagi masalah dengan warisan ialah kami mendedahkan semua kaedah superclass kepada pelanggan dan jika superclass kami tidak direka bentuk dengan betul dan terdapat lubang keselamatan, maka walaupun kami melaksanakan pelaksanaan terbaik kelas kami, kami terjejas oleh pelaksanaan yang lemah. daripada kelas super. Komposisi membantu kami menyediakan akses terkawal kepada kaedah superclass, manakala warisan tidak memberikan kawalan ke atas kaedah superclass. Ini juga merupakan salah satu faedah utama komposisi daripada warisan.

  3. Satu lagi kelebihan komposisi ialah ia membolehkan fleksibiliti dalam kaedah panggilan. Pelaksanaan kelas kami ClassCyang dibentangkan di atas tidak optimum dan memastikan masa penyusunan terikat dengan kaedah yang akan dipanggil. Dengan perubahan yang minimum, kami boleh membuat panggilan kaedah fleksibel dan dinamik.

    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();
    	}
    }

    Hasil daripada program yang dibentangkan di atas:

    doSomething implementation of A
    doSomething implementation of B

    Fleksibiliti dalam panggilan kaedah ini tidak tersedia dengan warisan, yang menambah manfaat lain pada pilihan gubahan.

  4. Pengujian unit lebih mudah dilakukan dengan komposisi kerana kami tahu bahawa kami menggunakan semua kaedah daripada kelas super dan boleh menyalinnya untuk ujian. Sedangkan dalam pewarisan kita lebih bergantung kepada superclass dan tidak tahu semua kaedah superclass yang akan digunakan. Jadi kita perlu menguji semua kaedah superclass, yang merupakan kerja tambahan kerana warisan.

    Sebaik-baiknya, kita hanya perlu menggunakan warisan apabila hubungan subkelas kepada superclass ditakrifkan sebagai "adalah". Dalam semua kes lain, disyorkan untuk menggunakan komposisi.

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