Java是當(dāng)今最流行的面向?qū)ο缶幊陶Z(yǔ)言之一。由于它是獨(dú)立于平臺(tái)的,因此您可以在每種類(lèi)型的設(shè)備和每個(gè)操作系統(tǒng)上找到 Java 應(yīng)用程序。而且由于Java相對(duì)容易學(xué)習(xí),因此它是許多程序員學(xué)習(xí)的第一批語(yǔ)言之一。
您應(yīng)該熟悉的 Java 的一個(gè)重要特性是類(lèi)繼承。繼承允許程序員通過(guò)促進(jìn)類(lèi)重用來(lái)優(yōu)化代碼。如果可以重用已經(jīng)過(guò)測(cè)試和調(diào)試的代碼,軟件開(kāi)發(fā)生命周期將變得更短且成本更低。
雖然理論上是一個(gè)簡(jiǎn)單的概念,但編碼繼承關(guān)系需要注意細(xì)節(jié)。對(duì)于多重繼承尤其如此,其中單個(gè)子類(lèi)從多個(gè)父類(lèi)繼承屬性。
Java拒絕多重繼承關(guān)系,因?yàn)樗鼈儠?huì)產(chǎn)生歧義,但是如果您知道該怎么做,有幾種方法可以實(shí)現(xiàn)許多相同的效果。
在本文中,我們將研究多重繼承的問(wèn)題,并討論Java中的替代編碼選項(xiàng)。
繼承術(shù)語(yǔ)
有時(shí),要成為一名成功的程序員,你必須學(xué)會(huì)解決問(wèn)題,以便找到常見(jiàn)錯(cuò)誤或問(wèn)題的解決方法。這是安全智能編碼的必要部分。
其中一個(gè)問(wèn)題涉及Java中的多重繼承(或者更確切地說(shuō),缺乏多重繼承)。
要完全理解 Java 中的繼承,您需要熟悉基本的面向?qū)ο缶幊?(OOP) 繼承術(shù)語(yǔ)。
類(lèi): 類(lèi)是面向?qū)ο缶幊陶Z(yǔ)言中的基本模板結(jié)構(gòu)。類(lèi)定義一組對(duì)象的公共屬性。
父類(lèi):父類(lèi)也稱(chēng)為基類(lèi)或超類(lèi),是為子類(lèi)提供功能的可擴(kuò)展類(lèi)。這就是可重用性發(fā)揮作用的地方。創(chuàng)建子類(lèi)時(shí),將重用父類(lèi)定義和函數(shù)。
兒童班:更一般地稱(chēng)為子類(lèi),子類(lèi)從另一個(gè)類(lèi)繼承特征。子類(lèi)是擴(kuò)展類(lèi)或派生類(lèi)。
遺產(chǎn):父類(lèi)和子類(lèi)之間的關(guān)系。
輸出讀取繼承類(lèi)型
目前有許多流行的面向?qū)ο缶幊陶Z(yǔ)言在使用,包括 Java、C++、JavaScript、Python、PHP、Ruby 和 Perl。雖然繼承是這些 OOP 語(yǔ)言的常見(jiàn)概念,但并非所有繼承類(lèi)型都存在于每種語(yǔ)言中。
了解您正在使用的特定語(yǔ)言中的一般繼承類(lèi)型和繼承限制至關(guān)重要。您對(duì)繼承的了解越多,您就越能有效地成為一名軟件開(kāi)發(fā)人員。
Java 支持的繼承類(lèi)型包括:
單級(jí)繼承:當(dāng)子類(lèi)從單個(gè)父類(lèi)派生功能時(shí)。
多級(jí)繼承:這是單級(jí)繼承的分層形式。在多級(jí)繼承中,子類(lèi)還可以充當(dāng)其他子類(lèi)的父類(lèi)。每個(gè)級(jí)別之間的關(guān)系都是線性的 - 沒(méi)有分支像多重繼承那樣延伸到上面。然后,最終的子類(lèi)具有其上方每個(gè)級(jí)別的功能。
分層繼承:與多重繼承相反。在分層繼承中,單個(gè)父類(lèi)具有多個(gè)子類(lèi)。因此,它不是在上面有分支,而是在下面分支。
混合繼承:顧名思義,混合繼承是其他繼承類(lèi)型的組合。
除了上面的繼承類(lèi)型之外,Java 還支持其他類(lèi)型。
多重繼承:在多重繼承中,一個(gè)子類(lèi)具有多個(gè)父類(lèi)。雖然 Java 和 JavaScript 不支持多重繼承,但 OOP 語(yǔ)言(如C++支持多重繼承)
多路徑繼承:多級(jí)、多級(jí)和分層繼承的混合體,在多路徑繼承中,子類(lèi)從父類(lèi)和父類(lèi)的多個(gè)子類(lèi)派生其特性和功能。因?yàn)槎嗦窂嚼^承依賴(lài)于多重繼承,所以 Java 不支持它的使用。
為什么 Java 不支持多重繼承
多重繼承的主要問(wèn)題是,它有可能在子類(lèi)中產(chǎn)生歧義。在1995年的概述白皮書(shū)中,Java首席設(shè)計(jì)師詹姆斯·高斯林(James Gosling)指出,多重繼承的問(wèn)題是創(chuàng)建Java的動(dòng)機(jī)之一。
多重繼承所固有的困難在鉆石問(wèn)題中表現(xiàn)得最為明顯。在菱形問(wèn)題中,父類(lèi) A 有兩個(gè)不同的子類(lèi) B 和 C;也就是說(shuō),子類(lèi) B 和 C 擴(kuò)展了類(lèi) A。
現(xiàn)在我們創(chuàng)建一個(gè)新的子類(lèi) D,它同時(shí)擴(kuò)展了類(lèi) B 和類(lèi) C.請(qǐng)注意,我們有多重繼承(D 擴(kuò)展 B 和 C)、分層繼承(B 和 C 擴(kuò)展 A)和多級(jí)繼承(D 擴(kuò)展 A、B 和 C)。
在菱形問(wèn)題中,子類(lèi) B 和 C 從父類(lèi) A 繼承方法。B 和 C 都重寫(xiě)繼承的方法。但是B和C中的新方法相互沖突。
終極子類(lèi) D 從其多個(gè)父級(jí) B 和 C 繼承兩個(gè)獨(dú)立且沖突的方法。不清楚應(yīng)該使用哪種方法類(lèi)D,因此存在歧義。其他 OOP 編程語(yǔ)言實(shí)現(xiàn)了各種方法來(lái)解決多重繼承歧義。
如何解決Java中的多重繼承問(wèn)題
僅僅因?yàn)槎嘀乩^承有問(wèn)題并不意味著它沒(méi)有用。在許多情況下,您可能希望一個(gè)類(lèi)具有來(lái)自其他多個(gè)類(lèi)的功能。
想想當(dāng)你成為一個(gè)非常成功的軟件開(kāi)發(fā)人員時(shí),你會(huì)買(mǎi)到特斯拉跑車(chē)。它將從跑車(chē)類(lèi)和電動(dòng)汽車(chē)類(lèi)中汲取特征。
或者,也許您正在使用私有瀏覽器閱讀本文,該文章具有在線數(shù)據(jù)隱私解決方案類(lèi)和常規(guī) Internet 瀏覽器類(lèi)的功能。
但是你不能在Java中擴(kuò)展多個(gè)類(lèi)。那么Java如何處理多重繼承問(wèn)題呢?
好吧,它使用稱(chēng)為接口的結(jié)構(gòu)。接口是抽象類(lèi)型,用于指定要實(shí)現(xiàn)的類(lèi)的行為。由于它們是抽象的,因此接口不包含有關(guān)其行為的詳細(xì)說(shuō)明。相反,這些類(lèi)提供了接口行為的具體實(shí)現(xiàn)。
接口具有以下幾個(gè)定義特征:
與類(lèi)不同,您不實(shí)例化接口。相反,類(lèi)實(shí)現(xiàn)接口
接口僅包含公共常量定義和方法標(biāo)頭
接口只能擴(kuò)展其他接口,而不能擴(kuò)展類(lèi)
接口可以擴(kuò)展多個(gè)接口,類(lèi)可以實(shí)現(xiàn)多個(gè)接口
現(xiàn)在,我們可以有效地繞過(guò)接口的菱形問(wèn)題?;叵胍幌?,只有接口只能擴(kuò)展其他接口,并且任何需要多個(gè)繼承特征的類(lèi)都必須實(shí)現(xiàn)多個(gè)接口,我們可以重新定義菱形問(wèn)題類(lèi)。
以前的類(lèi) A、B 和 C 現(xiàn)在變成了接口 A、B 和 C.接口 B 和 C 仍然擴(kuò)展了接口 A,但這些接口中沒(méi)有具體的函數(shù),只有定義的行為。類(lèi) D 仍然是一個(gè)類(lèi),它負(fù)責(zé)接口 B 和 C 中的行為的具體實(shí)現(xiàn)。
請(qǐng)注意此處的一個(gè)關(guān)鍵區(qū)別:D 類(lèi)不是擴(kuò)展接口 B 和 C。相反,它正在實(shí)施它們。因此,您實(shí)際上沒(méi)有多重繼承。相反,你只是重新定義了問(wèn)題。
了解繼承對(duì)于任何有效的編碼人員都是必要的。對(duì)于 Java 程序員來(lái)說(shuō),了解繼承的局限性以及針對(duì)傳統(tǒng)多重繼承問(wèn)題的內(nèi)置 Java 解決方法同樣重要。
學(xué)習(xí)如何在Java中放置接口以重新創(chuàng)建多重繼承的效果將提高您的效率和可雇用性。