JavaRush /Blog Java /Random-MS /Warisan vs komposisi di Jawa
dio
Tahap
Москва

Warisan vs komposisi di Jawa

Diterbitkan dalam kumpulan
Artikel ini menggambarkan konsep pewarisan dan gubahan di Jawa. Contoh pertama menunjukkan warisan dan kemudian menunjukkan cara memperbaik reka bentuk warisan menggunakan gubahan. Kami akan meringkaskan cara memilih antara mereka pada akhirnya. Warisan vs Komposisi di Jawa - 1

1. Warisan

Katakan kita mempunyai kelas Insect(serangga Inggeris) Kelas ini mengandungi dua kaedah: 1. move()(dari bahasa Inggeris bergerak) dan 2. attack()(dari serangan Inggeris)
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 menentukan kelas Bee(lebah Inggeris), yang merupakan salah satu jenis Insect, tetapi mempunyai pelaksanaan yang berbeza attack()dan move(). Ini boleh dilakukan 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();
	}
}
Gambar rajah hierarki kelas agak mudah: Warisan vs Komposisi di Jawa - 2Hasil pelaksanaan:
Fly
Fly
Attack
"Fly" ditaip dua kali, jadi kaedah move()dipanggil dua kali. Tetapi ia hanya perlu dipanggil sekali. Masalahnya disebabkan oleh super.attack(). Kaedah ini attack ()memanggil kaedah move()kelas Insect. Apabila subkelas memanggil super.attack (), ia juga memanggil kaedah yang diganti move(). Untuk menyelesaikan masalah kita boleh:
  1. Hapuskan attack()kaedah subkelas. Ini akan menjadikan subkelas bergantung pada attack()pelaksanaan kaedah superclass. Jika attack()attack()superclass mula menggunakan kaedah yang berbeza untuk bergerak, subclass perlu berubah juga. Ini adalah enkapsulasi yang buruk.
  2. Tulis semula kaedah attack()seperti berikut:

    public void attack() {
    	move();
    	System.out.println("Attack");
    }
  3. Ini menjamin hasil yang betul kerana subkelas tidak lagi bergantung pada superclass. Walau bagaimanapun, kod itu adalah pendua superclass. (kaedah attack()melakukan perkara yang lebih kompleks daripada hanya mengeluarkan rentetan). Ini bukan reka bentuk perisian yang baik dan tidak sepatutnya ada kod pendua.

Reka bentuk warisan ini adalah buruk kerana subkelas bergantung pada butiran pelaksanaan kelas supernya. Jika superclass berubah, subclass tidak akan berfungsi dengan betul.

2. Komposisi

Anda boleh menggunakan komposisi dan bukannya warisan. Mari lihat penyelesaian menggunakannya. Fungsi ini attack()diabstraksikan sebagai antara muka.
interface Attack {
	public void move();
	public void attack();
}
Jenis serangan yang berbeza boleh ditakrifkan dengan melaksanakan antara muka 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);
	}
}
Oleh kerana fungsi serangan adalah luaran, kelas Insecttidak lagi mengandunginya.
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;
	}
}
Kelas Bee(dari English Bee), bagaimana jenis Insectboleh 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();
	}
}
Gambar rajah kelas: Warisan vs Komposisi di Jawa - 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();
	}
}
Keputusan pelaksanaan:
fly
move
fly
sting

3. Bila hendak menggunakan pendekatan ini?

2 perkara berikut boleh membantu anda memutuskan antara warisan dan gubahan:
  1. Jika anda berurusan dengan hubungan antara kelas dalam bentuk "IS" dan kelas ingin menyediakan semua antara mukanya kepada kelas lain, maka warisan adalah lebih baik.
  2. jika perhubungan adalah "HAS", maka komposisi diutamakan.
Oleh itu, pewarisan dan komposisi mempunyai aplikasi mereka sendiri dan ia patut memahami merit mereka. Pautan:
  1. Bloch, Joshua. java berkesan. Pearson Education 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...
Pautan ke artikel asal Diterjemah
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION