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