日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java中的多重继承与组合vs继承

發(fā)布時(shí)間:2023/12/3 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中的多重继承与组合vs继承 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

有時(shí)我寫了幾篇有關(guān)Java 繼承接口組成的文章。 在這篇文章中,我們將研究多重繼承,然后學(xué)習(xí)組成優(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)如下所示,它擴(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不支持類中的多重繼承的主要原因。

請注意,上述具有多類繼承的問題也可能只出現(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來同時(shí)利用類方法和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í)踐之一是“通過接口支持組合”,我們將研究一些偏愛這種方法的方面。

  • 假設(shè)我們有一個(gè)超類和子類,如下所示:

    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è)級(jí)別的類繼承,并且超類不受我們控制,我們別無選擇,只能更改子類方法簽名或名稱以消除編譯錯(cuò)誤,我們還必須在所有方面進(jìn)行更改子類方法被調(diào)用的地方,因此繼承使我們的代碼易碎。

    組合永遠(yuǎn)不會(huì)發(fā)生上述問題,這使其比繼承更有利。

  • 繼承的另一個(gè)問題是,我們將所有超類方法公開給客戶端,并且如果我們的超類設(shè)計(jì)不當(dāng)且存在安全漏洞,那么即使我們在實(shí)現(xiàn)類時(shí)全力以赴,我們也會(huì)受到不佳實(shí)現(xiàn)的影響。超類。
    組合可以幫助我們提供對超類方法的受控訪問,而繼承不提供對超類方法的任何控制,這也是組合優(yōu)于繼承的主要優(yōu)勢之一。
  • 組合的另一個(gè)好處是它提供了方法調(diào)用的靈活性。 我們上ClassC實(shí)現(xiàn)不是最佳的,它提供了與將要調(diào)用的方法的編譯時(shí)綁定,只需進(jìn)行很小的更改,我們就可以靈活地使方法調(diào)用并使之動(dòng)態(tài)。

    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)用的靈活性在繼承中不可用,從而提倡了最佳做法,即在繼承方面偏向于組合。

  • 單元測試很容易組合,因?yàn)槲覀冎莱愔姓谑褂玫乃蟹椒?#xff0c;并且可以對其進(jìn)行模擬,而在繼承中,我們很大程度上依賴于超類,并且不知道將使用超類的所有方法,因此我們需要要測試超類的所有方法,這是一項(xiàng)額外的工作,由于繼承,我們不需要這樣做。
  • 理想情況下,只有在所有情況下父類和子類的“ is-a ”關(guān)系均成立時(shí)才應(yīng)使用繼承,否則我們應(yīng)該繼續(xù)進(jìn)行組合。

    參考: Developer Recipes博客上的JCG合作伙伴 Pankaj Kumar的Java多重繼承與Composition vs Inheritance 。

    翻譯自: https://www.javacodegeeks.com/2013/08/multiple-inheritance-in-java-and-composition-vs-inheritance.html

    總結(jié)

    以上是生活随笔為你收集整理的Java中的多重继承与组合vs继承的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。