Бул макалада Java тorндеги мурас жана курамы түшүнүктөрү чагылдырылган. Биринчи мисал мурасты көрсөтөт, андан кийин курамын колдонуу менен мурастын дизайнын кантип жакшыртуу керектигин көрсөтөт. Биз аягында алардын ортосунда кантип тандоо керек экенин кыскача айтып беребиз.
1. Мурас
Бизде класс бар деп коёлуInsect
(англисче курт-кумурскалар) Бул класс эки ыкманы камтыйт: 1. move()
(англисче кыймылдан) жана 2. attack()
(англисче чабуулдан)
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
, ал класстын түрлөрүнүн бири болуп саналат Insect
, бирок 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();
}
}
Класстын иерархиялык диаграммасы абдан жөнөкөй: Аткаруу натыйжасы:
Fly
Fly
Attack
"Чымын" эки жолу терилгендиктен, ыкма move()
эки жолу аталат. Бирок аны бир гана жолу чакыруу керек. Көйгөй super.attack()
. Метод класс ыкмасын attack ()
чакырат . Субкласс чакырганда , ал жокко чыгарылган ыкманы да чакырат . Көйгөйдү чечүү үчүн биз: move()
Insect
super.attack ()
move()
- субкласс ыкмасын жок кылуу
attack()
. Бул субклассты суперкласстын методун ишке ашыруусуна көз каранды кылатattack()
. Эгердеattack()attack()
суперкласс жылдыруунун башка ыкмасын колдоно баштаса, субкласс да өзгөрүшү керек болот. Бул жаман капсула. -
Методду
attack()
төмөнкүдөй кайра жазыңыз:public void attack() { move(); System.out.println("Attack"); }
-
Бул туура натыйжага кепилдик берет, анткени субкласс мындан ары суперкласстан көз каранды эмес. Бирок, code суперкласстын дубликаты. (ыкма
attack()
сапты чыгарууга караганда татаалыраак нерселерди жасайт). Бул жакшы программалык дизайн эмес жана эч кандай дубликат code болбошу керек.
2. Композиция
Сиз мурастын ордуна композицияны колдоно аласыз. Аны колдонуу менен чечимди карап көрөлү. Функцияattack()
интерфейс катары абстракцияланган.
interface Attack {
public void move();
public void attack();
}
Чабуул интерфейсин ишке ашыруу аркылуу чабуулдун ар кандай түрлөрүн аныктоого болот.
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);
}
}
Чабуул функциясы тышкы болгондуктан, класс Insect
мындан ары аны камтыbyte.
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;
}
}
Класс Bee
(англисче аарыдан), тип кантип Insect
кол салышы мүмкүн.
// 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();
}
}
Класс диаграммасы:
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();
}
}
Аткаруу натыйжасы:
fly
move
fly
sting
3. Бул ыкмаларды качан колдонуу керек?
Төмөнкү 2 пункт мурастын жана курамынын ортосунда чечим чыгарууга жардам берет:- Эгерде сиз "IS" формасындагы класстардын ортосундагы мамиле менен алектенип жатсаңыз жана класс өзүнүн бардык интерфейстерин башка класска бергиси келсе, анда мураска артыкчылык берилет.
- байланыш "HAS" болсо, анда курамы артыкчылыктуу.
- Блох, Джошуа. Натыйжалуу java. Pearson Education Индия, 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