JavaRush /Java Blog /Random-ID /Warisan vs komposisi di Jawa
dio
Level 16
Москва

Warisan vs komposisi di Jawa

Dipublikasikan di grup Random-ID
Artikel ini menggambarkan konsep pewarisan dan komposisi di Java. Contoh pertama mendemonstrasikan pewarisan dan kemudian menunjukkan cara meningkatkan desain pewarisan menggunakan komposisi. Kami akan merangkum cara memilih di antara keduanya di bagian akhir. Warisan vs Komposisi di Java - 1

1. Warisan

Misalkan kita mempunyai sebuah kelas Insect(bahasa Inggris serangga). Kelas ini berisi dua metode: 1. move()(dari bahasa Inggris move) dan 2. attack()(dari bahasa Inggris serangan)
class Insect {
	private int size;
	private String color;

	public Insect(int size, String color) {
		this.size = size;
		this.color = color;
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public void move() {
		System.out.println("Move");
	}

	public void attack() {
		move(); //assuming an insect needs to move before attacking
		System.out.println("Attack");
	}
}
Sekarang Anda ingin mendefinisikan sebuah kelas Bee(Bahasa Inggris bee), yang merupakan salah satu tipe Insect, tetapi memiliki implementasi attack()dan move(). Ini dapat dilakukan dengan menggunakan warisan:
class Bee extends Insect {
	public Bee(int size, String color) {
		super(size, color);
	}

	public void move() {
		System.out.println("Fly");
	}

	public void attack() {
		move();
		super.attack();
	}
}
public class InheritanceVSComposition {
	public static void main(String[] args) {
		Insect i = new Bee(1, "red");
		i.attack();
	}
}
Diagram hierarki kelas cukup sederhana: Warisan vs Komposisi di Java - 2Hasil eksekusi:
Fly
Fly
Attack
"Fly" diketik dua kali, sehingga metode ini move()dipanggil dua kali. Tapi itu hanya boleh dipanggil sekali. Masalah tersebut disebabkan oleh super.attack(). Metode ini attack ()memanggil metode move()kelas Insect. Ketika subkelas memanggil super.attack (), ia juga memanggil metode yang diganti move(). Untuk memperbaiki masalah ini kita dapat:
  1. Hilangkan attack()metode subkelas. Hal ini akan membuat subkelas bergantung pada attack()implementasi metode superkelas. Jika attack()attack()superkelas mulai menggunakan metode perpindahan yang berbeda, subkelas juga perlu diubah. Ini adalah enkapsulasi yang buruk.
  2. Tulis ulang metodenya attack()sebagai berikut:

    public void attack() {
    	move();
    	System.out.println("Attack");
    }
  3. Hal ini menjamin hasil yang benar karena subkelas tidak lagi bergantung pada superkelas. Namun, kode tersebut merupakan duplikat dari superclass. (metode ini attack()melakukan hal-hal yang lebih kompleks daripada sekadar mengeluarkan string). Ini bukan desain perangkat lunak yang bagus dan tidak boleh ada kode duplikat.

Desain pewarisan ini buruk karena subkelas bergantung pada detail implementasi superkelasnya. Jika superclass berubah, subclass tidak akan berfungsi dengan benar.

2. Komposisi

Anda dapat menggunakan komposisi alih-alih warisan. Mari kita lihat solusi menggunakannya. Fungsi ini attack()diabstraksi sebagai antarmuka.
interface Attack {
	public void move();
	public void attack();
}
Berbagai jenis serangan dapat ditentukan dengan mengimplementasikan antarmuka Serangan.
class AttackImpl implements Attack {
	private String move;
	private String attack;

	public AttackImpl(String move, String attack) {
		this.move = move;
		this.attack = attack;
	}

	@Override
	public void move() {
		System.out.println(move);
	}

	@Override
	public void attack() {
		move();
		System.out.println(attack);
	}
}
Karena fungsi serangan bersifat eksternal, kelas Insecttidak lagi memuatnya.
class Insect {
	private int size;
	private String color;

	public Insect(int size, String color) {
		this.size = size;
		this.color = color;
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
}
Class Bee(dari bahasa Inggris Bee), bagaimana tipenya Insectdapat menyerang.
// This wrapper class wrap an Attack object
class Bee extends Insect implements Attack {
	private Attack attack;

	public Bee(int size, String color, Attack attack) {
		super(size, color);
		this.attack = attack;
	}

	public void move() {
		attack.move();
	}

	public void attack() {
		attack.attack();
	}
}
Diagram kelas: Warisan vs Komposisi di Java - 3
public class InheritanceVSComposition2 {
	public static void main(String[] args) {
		Bee a = new Bee(1, "black", new AttackImpl("fly", "move"));
		a.attack();

		// if you need another implementation of move()
		// there is no need to change Insect, we can quickly use new method to attack

		Bee b = new Bee(1, "black", new AttackImpl("fly", "sting"));
		b.attack();
	}
}
Hasil eksekusi:
fly
move
fly
sting

3. Kapan pendekatan ini digunakan?

2 poin berikut dapat membantu Anda memutuskan antara warisan dan komposisi:
  1. Jika Anda berurusan dengan hubungan antar kelas dalam bentuk "IS" dan suatu kelas ingin menyediakan semua antarmukanya ke kelas lain, maka pewarisan lebih disukai.
  2. jika hubungannya "HAS", maka komposisi lebih diutamakan.
Oleh karena itu, pewarisan dan komposisi memiliki penerapannya masing-masing dan perlu dipahami manfaatnya. Tautan:
  1. Bloch, Joshua. Java yang efektif. Pearson Pendidikan India, 2008
  2. https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance
  3. https://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should...
Tautan ke artikel asli Diterjemahkan
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION