Maramihang Pamana sa Java
Ang multiple inheritance ay ang kakayahang lumikha ng mga klase na may maraming parent na klase. Hindi tulad ng iba pang sikat na object-oriented na wika gaya ng C++, hindi sinusuportahan ng Java ang multiple class inheritance. Hindi niya ito sinusuportahan dahil sa posibilidad na makatagpo ng "problema sa brilyante" at sa halip ay mas pinipiling magbigay ng ilang uri ng komprehensibong diskarte upang malutas ito, gamit ang pinakamahusay na mga opsyon na makakamit natin ang katulad na resulta ng mana."Ang Problema sa Diamond"
Upang maunawaan ang problema sa brilyante nang mas simple, ipagpalagay natin na ang maramihang pamana ay sinusuportahan sa Java. Sa kasong ito, makakakuha tayo ng mga klase na may hierarchy na ipinapakita sa figure sa ibaba. Ipagpalagay natin na iyonSuperClass
ay isang abstract na klase na naglalarawan ng isang tiyak na pamamaraan, at ang mga klase
ClassA
at
ClassB
mga tunay na klase.
SuperClass.java
package com.journaldev.inheritance;
public abstract class SuperClass {
public abstract void doSomething();
}
ClassA.java
package com.journaldev.inheritance;
public class ClassA extends SuperClass{
@Override
public void doSomething(){
System.out.println("Какая-то реализация класса A");
}
//собственный метод класса ClassA
public void methodA(){
}
}
Ngayon, ipagpalagay natin na ang klase
ClassC
ay nagmamana mula sa
ClassA
at
ClassB
sa parehong oras, at sa parehong oras ay may sumusunod na pagpapatupad:
package com.journaldev.inheritance;
public class ClassC extends ClassA, ClassB{
public void test(){
//вызов метода родительского класса
doSomething();
}
}
Tandaan na ang pamamaraan
test()
ay tumatawag ng isang pamamaraan
doSomething()
ng parent class, na hahantong sa kalabuan dahil hindi alam ng compiler kung aling superclass na pamamaraan ang dapat tawagan. Dahil sa hugis ng class inheritance diagram sa sitwasyong ito, na kahawig ng outline ng faceted diamond, ang problema ay tinatawag na "Diamond Problem". Ito ang pangunahing dahilan kung bakit hindi sinusuportahan ng Java ang multiple class inheritance. Tandaan na ang problemang ito sa multiple class inheritance ay maaari ding mangyari sa tatlong klase na may hindi bababa sa isang karaniwang paraan.
Maramihang inheritance at interface
Maaaring napansin mo na lagi kong sinasabi ang "multiple inheritance is not supported between classes", ngunit ito ay sinusuportahan sa pagitan ng mga interface. Ang isang simpleng halimbawa ay ipinapakita sa ibaba:InterfaceA.java
package com.journaldev.inheritance;
public interface InterfaceA {
public void doSomething();
}
InterfaceB.java
package com.journaldev.inheritance;
public interface InterfaceB {
public void doSomething();
}
Pansinin na ang parehong mga interface ay may isang pamamaraan na may parehong pangalan. Ngayon sabihin nating mayroon tayong interface na nagmamana mula sa parehong mga interface.
InterfaceC.java
package com.journaldev.inheritance;
public interface InterfaceC extends InterfaceA, InterfaceB {
//метод, с тем же названием описан в InterfaceA и InterfaceB
public void doSomething();
Dito, ang lahat ay perpekto, dahil ang mga interface ay isang reserbasyon/paglalarawan lamang ng isang pamamaraan, at ang pagpapatupad ng pamamaraan mismo ay nasa kongkretong klase na nagpapatupad ng mga interface na ito, kaya walang posibilidad na makatagpo ng kalabuan na may maraming pamana ng mga interface. Ito ang dahilan kung bakit ang mga klase sa Java ay maaaring magmana mula sa maraming mga interface. Ipakita natin ito sa halimbawa sa ibaba.
InterfacesImpl.java
package com.journaldev.inheritance;
public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC {
@Override
public void doSomething() {
System.out.println("doSomething реализация реального класса ");
}
public static void main(String[] args) {
InterfaceA objA = new InterfacesImpl();
InterfaceB objB = new InterfacesImpl();
InterfaceC objC = new InterfacesImpl();
//все вызываемые ниже методы получат одинаковую реализацию конкретного класса
objA.doSomething();
objB.doSomething();
objC.doSomething();
}
}
Maaaring napansin mo na sa tuwing i-override ko ang isang pamamaraan na inilarawan sa isang superclass o sa isang interface, ginagamit ko ang @Override annotation. Ito ay isa sa tatlong built-in na Java annotation at dapat mong gamitin ito palagi kapag nag-o-override ng mga pamamaraan.
Komposisyon bilang kaligtasan
Paano kung gusto naming gumamit ng isangmethodA()
klase
ClassA
at pag-andar
methodB()
ng klase
ClassB
sa
ClassС
? Ang isang solusyon dito ay maaaring komposisyon - isang muling isinulat na bersyon
ClassC
na nagpapatupad ng parehong mga pamamaraan ng klase
ClassA
at
ClassB
mayroon ding pagpapatupad
doSomething()
para sa isa sa mga bagay.
ClassC.java
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();
}
}
Komposisyon o pamana?
Ito ay isang mahusay na kasanayan sa Java programming upang samantalahin ang komposisyon kaysa sa mana. Titingnan natin ang ilang aspeto na pabor sa diskarteng ito.-
Ipagpalagay na mayroon tayong sumusunod na kumbinasyon ng mga klase ng magulang at tagapagmana:
ClassC.java
package com.journaldev.inheritance; public class ClassC{ public void methodC(){ } }
ClassD.java
package com.journaldev.inheritance; public class ClassD extends ClassC{ public int test(){ return 0; } }
Ang code sa itaas ay nag-compile at gumagana nang maayos, ngunit paano kung
ClassC
iba itong ipinatupad:package com.journaldev.inheritance; public class ClassC{ public void methodC(){ } public void test(){ } }
Tandaan na ang pamamaraan
test()
ay umiiral na sa descendant class, ngunit nagbabalik ng resulta ng ibang uri. NgayonClassD
, kung sakaling gumagamit ka ng IDE, hindi ito mag-compile. Papayuhan kang baguhin ang uri ng pagbabalik sa descendant o superclass.Ngayon isipin natin ang isang sitwasyon kung saan mayroong multi-level inheritance ng mga klase at hindi available ang superclass para sa ating mga pagbabago. Ngayon, para maalis ang error sa compilation, wala kaming ibang opsyon kundi baguhin ang signature o pangalan ng subclass method. Kakailanganin din nating gumawa ng mga pagbabago sa lahat ng lugar kung saan tinawag ang pamamaraang ito. Kaya, ginagawang malutong ng pamana ang ating code.
Ang problemang inilarawan sa itaas ay hindi kailanman nangyayari sa kaso ng komposisyon, at samakatuwid ay ginagawang mas pinipili ang huli kaysa sa mana.
-
Ang susunod na problema sa mana ay ilantad namin ang lahat ng mga pamamaraan ng magulang sa kliyente. At kung ang superclass ay hindi idinisenyo nang tama at naglalaman ng mga butas sa seguridad. Pagkatapos, kahit na lubos nating pinangangalagaan ang seguridad sa pagpapatupad ng ating subclass, aasa pa rin tayo sa maling pagpapatupad ng parent class.
Tinutulungan tayo ng komposisyon sa pagbibigay ng kontroladong pag-access sa mga pamamaraan ng isang superclass, samantalang ang mana ay hindi nagpapanatili ng anumang kontrol sa mga pamamaraan nito. Ito rin ay isa sa mga pangunahing bentahe ng komposisyon kaysa sa mana.
-
Ang isa pang benepisyo ng komposisyon ay nagdaragdag ito ng kakayahang umangkop kapag tumatawag sa mga pamamaraan. Ang pagpapatupad ng klase
ClassC
na inilarawan sa itaas ay hindi optimal at gumagamit ng maagang pagbubuklod sa tinatawag na pamamaraan. Ang mga kaunting pagbabago ay magbibigay-daan sa amin na gawing flexible ang paraan ng pagtawag at magbibigay-daan para sa late binding (binding sa runtime).ClassC.java
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(); } }
Ipapakita ng program sa itaas ang:
doSomething implementation of A doSomething implementation of B
Ang kakayahang umangkop na ito sa paraan ng pagtawag ay hindi nakikita sa mana, na ginagawang komposisyon ang pinakamahusay na diskarte.
-
Ang pagsubok sa yunit ay mas madali sa kaso ng komposisyon dahil alam namin na para sa lahat ng mga pamamaraan na ginagamit sa superclass maaari naming i-stub ang mga pagsubok, habang sa pamana kami ay umaasa nang malaki sa superclass at hindi alam kung paano ang mga pamamaraan ng parent class gagamitin. Kaya, dahil sa pamana, kailangan nating subukan ang lahat ng mga pamamaraan ng superclass, na hindi kinakailangang gawain.
Sa isip, ang mana ay dapat lamang gamitin kapag ang " is-a " na relasyon ay totoo para sa mga klase ng magulang at anak, kung hindi, ang komposisyon ay dapat na mas gusto.
GO TO FULL VERSION