簡體   English   中英

類擴展多個Java類?

[英]Class extending more than one class Java?

我知道一個類可以實現多個接口,但是可以擴展多個類嗎? 例如,我希望我的類擴展TransformGroup和我創建的類。 這在Java中可行嗎? 兩個語句class X extends TransformGroup extends Yclass X extends TransformGroup, Y接收錯誤。 如果不可能,為什么? TransformGroup擴展了Group但我想它也擴展了Node因為它繼承了Node字段,並且可以在需要Node對象的地方傳遞。 此外,與Java中的所有類一樣,它們擴展了Object類。 那么為什么不能用多個類擴展呢?

TransformGroup繼承

那么,如果可能的話,做到這一點的正確方法是什么? 如果沒有,為什么以及如何解決問題呢?

在Java中,不允許多重繼承。 作為設計決策,它被排除在語言之外,主要是為了避免循環依賴。

場景1:如您所知,Java中無法實現以下功能:

public class Dog extends Animal, Canine{

}

場景2:但是以下是可能的:

public class Canine extends Animal{

}

public class Dog extends Canine{

}

這兩種方法的不同之處在於,在第二種方法中,有一個明確定義的父類或super類,而在第一種方法中, super類是模糊的。

考慮AnimalCanine是否都有方法drink() 如果我們調用Dog.drink()在第一個場景下調用父方法? 在第二種情況下,我們知道只要Dog沒有覆蓋它,調用Dog.drink()就會調用Canine類的drink方法。

不,這在Java中是不可能的(也許在java 8中它將是可用的)。 除了在樹中延伸的情況。 例如:

class A
class B extends A
class C extends B

在Java中,不允許對接口的實現(類)進行多重繼承:

interface A extends B, C

例如, MouseInputListener擴展了MouseListener和MouseMotionListener

當然,一個類可以實現幾個接口:

class X implements A, F

Java中沒有多重繼承的概念。 只能實現多個接口。

類無法實現多重繼承,您可以在界面的幫助下實現它,而不是使用類。 它是由java語言設計的。 看看James gosling的評論。

作者:James Gosling在1995年2月給出了為什么Java中不支持多繼承的想法。

JAVA省略了許多很少使用,知之甚少,令人困惑的C ++特性,這些特性在我們的經驗中帶來了比利益更多的悲傷。 這主要包括運算符重載(盡管它確實有方法重載),多重繼承和廣泛的自動強制。

多重繼承http://bit.ly/1Z62XjI

假設B和C重寫了繼承的方法和它們自己的實現。 現在D使用多重繼承繼承了B&C。 D應該繼承被重寫的方法。問題是將使用哪個重寫方法? 它會來自B還是C? 在這里,我們有一個模棱兩可。 為了排除這種情況,Java中沒有使用多重繼承。

Java沒有提供多重繼承。
當你說A擴展B時,則意味着A擴展B而B擴展了Object。
它並不意味着A擴展B,Object。

class A extends Object
class B extends A

java不能支持多重繼承。但是你可以這樣做

class X
{
}
class Y extends X
{
}
class Z extends Y{
}

給出的大多數答案似乎都假設我們要繼承的所有類都是由我們定義的。

但是,如果其中一個類沒有被我們定義,即我們無法改變其中一個類繼承的內容,因此無法使用已接受的答案,那么會發生什么呢?

那么答案取決於我們是否至少有一個類是由我們定義的。 即在我們想要繼承的類列表中存在一個類A ,其中A由我們創建。

除了已經接受的答案之外,我還提出了3個多重繼承問題的實例以及每個問題的可能解決方案。

繼承類型1

好吧,你想要一個C類擴展類AB ,其中B是在其他地方定義的類,但A由我們定義。 我們可以做的是將A轉換為接口,然后C類可以在擴展B A同時實現A

class A {}
class B {} // Some external class
class C {}

變成

interface A {}
class AImpl implements A {}
class B {} // Some external class
class C extends B implements A

繼承類型2

現在假設您有兩個以上的類繼承,同樣的想法仍然存在 - 除了其中一個類之外,所有類都必須由我們定義。 所以說我們希望類A繼承以下類, BC ,... X ,其中X是我們外部的類,即在其他地方定義的類。 我們應用相同的想法將所有其他類,但最后一個轉換為接口,然后我們可以:

interface B {}
class BImpl implements B {}
interface C {}
class CImpl implements C {}
...
class X {}
class A extends X implements B, C, ...

繼承類型3

最后,還有一些情況,你只有一堆類繼承,但沒有一個是你定義的。 這有點棘手,但可以通過使用委托來實現 委托允許一個類A假裝是其他一些類B但任何呼叫A中定義一些公共方法B ,實際上是調用類型的對象代表B並返回結果。 這使得A類成為我稱之為Fat class

這有什么用?

嗯,這很簡單。 您創建一個接口,指定您想要使用的外部類中的公共方法,以及您正在創建的新類中的方法,然后您的新類實現該接口。 這可能聽起來令人困惑,所以讓我更好地解釋一下。

最初我們有以下外部類BCD ,..., X ,我們希望我們的新類A繼承所有這些類。

class B {
    public void foo() {}
}

class C {
    public void bar() {}
}

class D {
    public void fooFoo() {}
}

...

class X {
    public String fooBar() {}
}

接下來,我們創建一個接口A ,它公開以前在類A中的公共方法以及上述類中的公共方法

interface A {
    void doSomething(); // previously defined in A
    String fooBar(); // from class X
    void fooFoo(); // from class D
    void bar(); // from class C
    void foo(); // from class B
}

最后,我們創建一個實現接口A的類AImpl

class AImpl implements A {
    // It needs instances of the other classes, so those should be
    // part of the constructor
    public AImpl(B b, C c, D d, X x) {}
    ... // define the methods within the interface
}

你有它! 這是一種偽繼承,因為類型A的對象不是我們開始使用的任何外部類的嚴格后代,而是公開了一個接口,該接口定義了與這些類中相同的方法。

您可能會問,為什么我們不只是創建一個定義我們想要使用的方法的類,而不是定義一個接口。 為什么我們不只是有一個包含我們想要繼承的類的公共方法的A類? 這樣做是為了減少耦合 我們不希望使用A類必須過多地依賴於類A (因為類往往會改變很多),而是依賴於接口A給出的承諾。

Java不允許擴展多個類。

我們假設C類正在擴展A和B類。 然后假設A和B類具有相同名稱的方法(例如:method1())。 考慮一下代碼:

C obj1 = new C(); obj1.method1(); - 這里JVM不了解它需要訪問哪種方法。 因為A和B類都有這種方法。 因此我們將JVM置於兩難境地,這就是為什么從Java中刪除多重繼承的原因。 並且正如所說的實現多個類將解決此問題。

希望這有所幫助。

你好請注意像真正的工作。

孩子不能有兩個母親

所以在java中,子類不能有兩個父類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM