JavaRush /Java Blog /Random-ID /Warisan berganda di Jawa. Komposisi vs. Warisan
DSergey_Kh
Level 12

Warisan berganda di Jawa. Komposisi vs. Warisan

Dipublikasikan di grup Random-ID

Warisan Berganda di Jawa

Warisan berganda memungkinkan Anda membuat kelas yang mewarisi beberapa superkelas. Tidak seperti beberapa bahasa pemrograman berorientasi objek populer lainnya, seperti C++, Java tidak mengizinkan pewarisan berganda dari kelas. Java tidak mendukung pewarisan banyak kelas karena dapat menyebabkan masalah berlian. Dan daripada mencari cara untuk menyelesaikan masalah ini, ada pilihan yang lebih baik bagaimana kita bisa mencapai hasil yang sama seperti pewarisan berganda.

Masalah berlian

Untuk memahami masalah berlian dengan lebih mudah, asumsikan bahwa pewarisan berganda didukung di Java. Dalam hal ini, kita dapat memiliki hierarki kelas seperti yang ditunjukkan pada gambar di bawah. Множественное наследование в Java. Композиция в сравнении с Наследованием - 1Mari kita asumsikan bahwa kelas SuperClasstersebut abstrak dan beberapa metode dideklarasikan di dalamnya. Baik kelas konkrit ClassAmaupun 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 anggaplah kita ingin menerapkan ClassCdan mewarisinya dari ClassAdan ClassB.
package com.journaldev.inheritance;
public class ClassC extends ClassA, ClassB{
	public void test(){
		//calling super class method
		doSomething();
	}
}
Perhatikan bahwa metode ini test()memanggil metode superclass doSomething(). Hal ini menyebabkan ambiguitas karena kompiler tidak mengetahui metode superkelas mana yang harus dieksekusi. Ini adalah diagram kelas berbentuk berlian yang disebut masalah berlian. Inilah alasan utama mengapa Java tidak mendukung pewarisan berganda. Perhatikan bahwa masalah pewarisan beberapa kelas di atas hanya dapat terjadi dengan tiga kelas yang memiliki setidaknya satu metode umum.

Warisan Antarmuka Berganda

Di Java, pewarisan berganda tidak didukung di kelas, namun didukung di antarmuka. Dan satu antarmuka dapat memperluas banyak antarmuka lainnya. Di bawah ini adalah contoh sederhana.
package com.journaldev.inheritance;
public interface InterfaceA {
	public void doSomething();
}
package com.journaldev.inheritance;
public interface InterfaceB {
	public void doSomething();
}
Perhatikan bahwa kedua antarmuka mendeklarasikan metode yang sama. Sekarang kita dapat membuat antarmuka yang memperluas kedua antarmuka tersebut, seperti yang ditunjukkan pada 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 karena antarmuka hanya mendeklarasikan metode dan implementasinya akan dilakukan di kelas yang mewarisi antarmuka. Jadi, tidak ada cara untuk mendapatkan ambiguitas dalam pewarisan banyak antarmuka.
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();
	}
}
Harap dicatat bahwa setiap kali Anda mengganti metode superclass atau mengimplementasikan metode antarmuka, gunakan anotasi @Override. Bagaimana jika kita ingin menggunakan fungsi methodA()suatu kelas ClassAdan fungsi methodB()suatu kelas ClassBdalam suatu kelas ClassC? Solusinya terletak pada penggunaan komposisi. Di bawah ini adalah versi kelas ClassCyang menggunakan komposisi untuk mendefinisikan metode kelas dan metode 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 vs. Warisan

Salah satu praktik pemrograman Java terbaik adalah “menyetujui komposisi sebelum pewarisan.” Kami akan mengeksplorasi beberapa aspek yang mendukung pendekatan ini.
  1. Katakanlah kita memiliki superclass dan kelas yang memperluasnya:

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

    Kode di atas dikompilasi dan berfungsi dengan baik. Namun bagaimana jika kita mengubah implementasi kelasnya ClassCseperti gambar di bawah ini:

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

    Perhatikan bahwa metode ini test()sudah ada di subkelas, tetapi tipe pengembaliannya berbeda. Sekarang kelas ClassDtidak akan dikompilasi dan jika Anda menggunakan IDE apa pun, Anda akan diminta untuk mengubah tipe pengembalian di superkelas atau subkelas.

    Sekarang bayangkan sebuah situasi di mana kita memiliki hierarki pewarisan kelas multi-level dan tidak memiliki akses ke superkelas. Kami tidak punya pilihan selain mengubah tanda tangan metode subkelas atau namanya untuk menghilangkan kesalahan kompilasi. Kita juga harus mengubah metode subkelas di semua tempat pemanggilannya. Jadi, warisan membuat kode kita rapuh.

    Masalah di atas tidak akan pernah terjadi pada komposisi dan ini membuatnya lebih menarik untuk diwariskan.

  2. Masalah lain dengan pewarisan adalah kita mengekspos semua metode superclass ke klien dan jika superclass kita tidak dirancang dengan benar dan terdapat celah keamanan, maka meskipun kita mengimplementasikan implementasi terbaik dari kelas kita, kita akan terpengaruh oleh implementasi yang buruk. dari kelas super. Komposisi membantu kita menyediakan akses terkontrol ke metode superkelas, sedangkan pewarisan tidak memberikan kontrol atas metode superkelas. Ini juga salah satu manfaat utama komposisi dari warisan.

  3. Manfaat lain dari komposisi adalah memungkinkan fleksibilitas dalam metode pemanggilan. Implementasi kami terhadap kelas ClassCyang disajikan di atas tidak optimal dan memastikan bahwa waktu kompilasi terikat dengan metode yang akan dipanggil. Dengan sedikit perubahan kita dapat membuat pemanggilan metode menjadi fleksibel dan dinamis.

    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 dari program yang disajikan di atas:

    doSomething implementation of A
    doSomething implementation of B

    Fleksibilitas dalam pemanggilan metode ini tidak tersedia dengan pewarisan, sehingga menambah manfaat lain pada pilihan komposisi.

  4. Pengujian unit lebih mudah dilakukan dengan komposisi karena kita tahu bahwa kita menggunakan semua metode dari superclass dan dapat menyalinnya untuk pengujian. Sedangkan dalam pewarisan kita lebih bergantung pada superclass dan tidak mengetahui semua metode superclass yang akan digunakan. Jadi kita harus menguji semua metode superclass, yang merupakan pekerjaan ekstra karena pewarisan.

    Idealnya, kita hanya boleh menggunakan pewarisan ketika hubungan subkelas ke superkelas didefinisikan sebagai "adalah". Dalam semua kasus lain, disarankan untuk menggunakan komposisi tersebut.

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