多重继承java_Java中的多重继承与组合vs继承
多重繼承java
有時我寫了幾篇有關Java 繼承 , 接口和組成的文章。 在這篇文章中,我們將研究多重繼承,然后了解組成優(yōu)于繼承的好處。
Java中的多重繼承
多重繼承是創(chuàng)建具有多個超類的單個類的能力。 與其他一些流行的面向?qū)ο蟮木幊陶Z言(如C ++)不同, java不提供對類中多重繼承的支持 。 Java不支持類中的多重繼承,因為它可能導致菱形問題 ,而不是提供一些復雜的方法來解決它,而是有更好的方法來實現(xiàn)與多重繼承相同的結(jié)果。
鉆石問題
為了輕松理解鉆石問題,我們假設Java中支持多重繼承。 在這種情況下,我們可以像下面的圖像那樣有一個類層次結(jié)構(gòu)。
假設SuperClass是一個抽象類,聲明了一些方法,而ClassA,ClassB是具體類。
超類.java
package com.journaldev.inheritance;public abstract class SuperClass {public abstract void doSomething(); }ClassA.java
package com.journaldev.inheritance;public class ClassA extends SuperClass{@Overridepublic void doSomething(){System.out.println("doSomething implementation of A");}//ClassA own methodpublic void methodA(){} }ClassB.java
package com.journaldev.inheritance;public class ClassB extends SuperClass{@Overridepublic void doSomething(){System.out.println("doSomething implementation of B");}//ClassB specific methodpublic void methodB(){} }現(xiàn)在,讓我們說ClassC的實現(xiàn)類似于以下內(nèi)容,它擴展了ClassA和ClassB。
ClassC.java
package com.journaldev.inheritance;public class ClassC extends ClassA, ClassB{public void test(){//calling super class methoddoSomething();}}注意, test()方法正在調(diào)用超類doSomething()方法,這導致歧義,因為編譯器不知道要執(zhí)行哪個超類方法,并且由于菱形類圖,它被稱為Diamond Problem,這是Java不支持類中的多重繼承的主要原因。
請注意,具有多個類繼承的上述問題也可能只出現(xiàn)在三個類中,它們?nèi)烤哂兄辽僖粋€通用方法。
接口中的多重繼承
您可能已經(jīng)注意到,我一直在說類不支持多重繼承,但接口支持多重繼承,并且單個接口可以擴展多個接口,下面是一個簡單的示例。
接口A.java
package com.journaldev.inheritance;public interface InterfaceA {public void doSomething(); }接口B.java
package com.journaldev.inheritance;public interface InterfaceB {public void doSomething(); }注意,兩個接口都聲明了相同的方法,現(xiàn)在我們可以擁有一個擴展這兩個接口的接口,如下所示。
接口C.java
package com.journaldev.inheritance;public interface InterfaceC extends InterfaceA, InterfaceB {//same method is declared in InterfaceA and InterfaceB bothpublic void doSomething();}這樣做非常好,因為接口僅聲明方法,并且實際實現(xiàn)將由實現(xiàn)接口的具體類來完成,因此在接口的多重繼承中不存在任何歧義的可能性。
這就是為什么Java類可以實現(xiàn)多重繼承的原因,例如下面的示例。
接口Impl.java
package com.journaldev.inheritance;public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC {@Overridepublic void doSomething() {System.out.println("doSomething implementation of concrete class");}public static void main(String[] args) {InterfaceA objA = new InterfacesImpl();InterfaceB objB = new InterfacesImpl();InterfaceC objC = new InterfacesImpl();//all the method calls below are going to same concrete implementationobjA.doSomething();objB.doSomething();objC.doSomething();}}您是否注意到,每當我覆蓋任何超類方法或?qū)崿F(xiàn)任何接口方法時,我都使用@Override注釋,它是三個內(nèi)置的Java注釋之一,并且在覆蓋任何方法時都應始終使用覆蓋注釋 。
救援人員組成
因此,如果我們想在ClassC使用ClassA函數(shù)methodA()和ClassB函數(shù)methodB() ,該解決方案在于使用composition ,這是ClassC的重構(gòu)版本,該版本使用了composition來利用這兩種類方法以及doSomething ()方法來自其中一個對象。
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();} }組合與繼承
Java編程的最佳實踐之一是“通過接口支持組合”,我們將研究一些偏愛這種方法的方面。
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;} }上面的代碼可以編譯并正常工作,但是如果ClassC實現(xiàn)更改如下:
ClassC.java
package com.journaldev.inheritance;public class ClassC{public void methodC(){}public void test(){} }請注意,子類中已經(jīng)存在test()方法,但返回類型有所不同,現(xiàn)在ClassD將無法編譯,并且如果您使用的是任何IDE,它將建議您更改超類或子類中的返回類型。
現(xiàn)在想象一下這樣的情況:我們具有多個級別的類繼承,并且超類不受我們控制,我們別無選擇,只能更改子類方法簽名或名稱以消除編譯錯誤,我們還必須在所有方面進行更改子類方法被調(diào)用的地方,因此繼承使我們的代碼易碎。
上面的問題永遠不會在組合中發(fā)生,這使其比繼承更有利。
組合可以幫助我們提供對超類方法的受控訪問,而繼承不提供對超類方法的任何控制,這也是組合優(yōu)于繼承的主要優(yōu)勢之一。
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();} }上面程序的輸出是:
doSomething implementation of A doSomething implementation of B這種方法調(diào)用的靈活性在繼承中不可用,并提倡了最佳實踐,即在繼承方面偏向于組合。
理想情況下,僅當在所有情況下父類和子類的“ is-a ”關系均成立時才應使用繼承,否則我們應該繼續(xù)進行組合。
翻譯自: https://www.javacodegeeks.com/2013/08/multiple-inheritance-in-java-and-composition-vs-inheritance.html
多重繼承java
總結(jié)
以上是生活随笔為你收集整理的多重继承java_Java中的多重继承与组合vs继承的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在Jersey测试中模拟Security
- 下一篇: executor线程池框架_如何使用Ja