Bu məqalə Java-da miras və kompozisiya anlayışlarını təsvir edir. Birinci misal varisliyi nümayiş etdirir və sonra kompozisiyadan istifadə edərək miras dizaynını necə təkmilləşdirməyi göstərir. Sonda onlar arasında necə seçim edəcəyimizi ümumiləşdirəcəyik.
1. Vərəsəlik
Fərz edək ki, bizim bir sinifimiz varInsect
(İngiliscə həşərat) Bu sinifdə iki üsul var: 1. move()
(İngilis dili hərəkətindən) və 2. attack()
(İngilis hücumundan)
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");
}
}
Bee
İndi siz növlərdən biri olan , lakin və -nin Insect
müxtəlif tətbiqləri olan bir sinif (İngilis arısı) təyin etmək istəyirsiniz . Bu mirasdan istifadə etməklə edilə bilər: attack()
move()
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();
}
}
Sinif iyerarxiya diaqramı olduqca sadədir: İcra nəticəsi:
Fly
Fly
Attack
"Uçmaq" iki dəfə yazılır, buna görə də üsul move()
iki dəfə çağırılır. Ancaq yalnız bir dəfə çağırılmalıdır. Problem səbəb olur super.attack()
. Metod sinif metodunu attack ()
çağırır . Bir alt sinif çağırdıqda , o, həmçinin ləğv edilmiş metodu da çağırır . Problemi həll etmək üçün biz: move()
Insect
super.attack ()
move()
- Alt sinif metodunu aradan qaldırın
attack()
. Bu, alt sinfi supersinf metodunun həyata keçirilməsindən asılı edəcəkattack()
. Əgərattack()attack()
supersinif hərəkət etmək üçün başqa üsuldan istifadə etməyə başlayırsa, alt sinif də dəyişməlidir. Bu pis inkapsulyasiyadır. -
Metodunu
attack()
aşağıdakı kimi yenidən yazın:public void attack() { move(); System.out.println("Attack"); }
-
Bu, düzgün nəticəyə zəmanət verir, çünki alt sinif artıq supersinifdən asılı deyil. Bununla belə, kod superklassın dublikatıdır. (metod
attack()
yalnız bir sətir çıxarmaqdan daha mürəkkəb işlər görür). Bu yaxşı proqram dizaynı deyil və dublikat kod olmamalıdır.
2. Tərkibi
Siz miras əvəzinə kompozisiyadan istifadə edə bilərsiniz. Onu istifadə edərək həll yoluna baxaq. Funksiyaattack()
interfeys kimi mücərrədləşdirilmişdir.
interface Attack {
public void move();
public void attack();
}
Hücum interfeysini tətbiq etməklə müxtəlif hücum növləri müəyyən edilə bilər.
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);
}
}
Hücum funksiyası xarici olduğundan, sinif Insect
artıq onu ehtiva etmir.
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;
}
}
Sinif Bee
(İngilis Bee-dən), növün necə Insect
hücum edə biləcəyi.
// 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();
}
}
Sinif diaqramı:
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();
}
}
İcra nəticəsi:
fly
move
fly
sting
3. Bu yanaşmalardan nə vaxt istifadə edilməlidir?
Aşağıdakı 2 məqam varislik və kompozisiya arasında qərar verməyə kömək edə bilər:- Əgər siz "IS" formasının sinifləri arasındakı əlaqə ilə məşğul olursunuzsa və bir sinif bütün interfeyslərini başqa bir sinfə təqdim etmək istəyirsə, irsiyyətə üstünlük verilir.
- əlaqə "HAS" olarsa, kompozisiyaya üstünlük verilir.
- Bloch, Joshua. Effektiv java. Pearson Education India, 2008
- https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance
- https://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should...
GO TO FULL VERSION