クラスは複数のインターフェイスを実装できることを知っていますが、複数のクラスを拡張することは可能ですか?たとえば、クラスでTransformGroup
と作成したクラスの両方を拡張したいです。これはJavaで可能ですか?両方のステートメントclass X extends TransformGroup extends Y
およびclass X extends TransformGroup, Y
エラーを受け取ります。それが不可能な場合、なぜですか? TransformGroup
はGroup
を拡張しますが、Node
からフィールドを継承し、Node
オブジェクトの場所に渡すことができるため、Node
も拡張すると思います。必要とされている。また、Javaのすべてのクラスと同様に、Object
クラスを拡張します。それでは、なぜ複数のクラスで拡張できないのでしょうか?
それで、それが可能であれば、それを行う適切な方法は何ですか?そうでない場合、問題を解決する理由と方法を教えてください。
In Java多重継承は許可されていません。主に循環依存を回避するために、設計上の決定として言語から除外されました。
Scenario1:学習したとおり、Javaでは次のことは不可能です。
_public class Dog extends Animal, Canine{
}
_
シナリオ2:ただし、次のことが可能です。
_public class Canine extends Animal{
}
public class Dog extends Canine{
}
_
これら2つのアプローチの違いは、2番目のアプローチでは明確に定義された親またはsuper
クラスがありますが、最初のアプローチではsuper
クラスがあいまいです。
Animal
とCanine
の両方にメソッドdrink()
があったかどうかを検討してください。最初のシナリオでは、Dog.drink()
?を呼び出した場合、どの親メソッドが呼び出されますか? 2番目のシナリオでは、Dog.drink()
を呼び出すと、Canine
がオーバーライドしない限り、drink
クラスDog
メソッドを呼び出すことがわかります。
In Java多重継承は、インターフェースの実装(クラス)に対してのみ許可されていません。
interface A extends B, C
例えば。 MouseInputListener MouseListenerおよびMouseMotionListenerを拡張
そしてもちろん、クラスはいくつかのインターフェースを実装できます:
class X implements A, F
いいえ、Java(たぶんJava 8で利用可能になる)。
class A
class B extends A
class C extends B
Javaには多重継承の概念はありません。複数のインターフェイスのみを実装できます。
BとCが継承されたメソッドと独自の実装をオーバーライドしていると仮定します。現在、Dは多重継承を使用してBとCの両方を継承しています。 Dはオーバーライドされたメソッドを継承する必要があります。質問は、どのオーバーライドされたメソッドが使用されるのですか? BまたはCからですか?ここにはあいまいさがあります。このような状況を排除するために、Javaでは多重継承は使用されませんでした。
クラスでは多重継承はできません。クラスではなくインターフェイスの助けを借りて達成できます。 Java language。James James Goslingのコメントをご覧ください。
1995年2月のジェームズゴスリングは、多重継承がJavaでサポートされていない理由を説明しています。
Javaは、C++のほとんど使用されておらず、よく理解されていない、混乱を招く機能を省略しています。これは主に、演算子のオーバーロード(メソッドのオーバーロードはありますが)、多重継承、および広範な自動強制で構成されます。
Javaは多重継承を提供しませんでした。
AがBを拡張するということは、AがBを拡張し、Bがオブジェクトを拡張することを意味します。
AがB、Objectを拡張するという意味ではありません。
class A extends Object
class B extends A
Javaは多重継承をサポートできませんが、この方法でこれを行うことができます
class X
{
}
class Y extends X
{
}
class Z extends Y{
}
与えられた答えのほとんどは、継承しようとしているすべてのクラスが私たちによって定義されていると仮定しているようです。
しかし、クラスの1つが私たちによって定義されていない場合、つまり、それらのクラスの1つが継承するものを変更できず、したがって受け入れられた答えを利用できない場合はどうなりますか?
答えは、少なくとも1つのクラスが定義されているかどうかによって異なります。すなわち、継承したいクラスのリストの中にクラスA
が存在します。ここでA
は私たちによって作成されます。
すでに受け入れられている答えに加えて、この多重継承問題のさらに3つのインスタンスと、それぞれの可能な解決策を提案します。
クラスC
にクラスA
およびB
を拡張したいとします。ここで、B
は別の場所で定義されたクラスですが、A
は私たちによって定義されています。これでできることは、A
をインターフェイスに変えることです。クラスC
はA
を拡張しながらB
を実装できます。
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
ここで、継承するクラスが3つ以上あるとしましょう。同じ考え方が依然として有効です。1つを除くすべてのクラスを定義する必要があります。したがって、クラスA
を次のクラスB
、C
、... X
から継承させたいとします。ここでX
は私たちの外部にある、つまりどこかで定義されたクラスです。他のすべてのクラスをインターフェイスに変換するという同じ考え方を適用すると、次のようになります。
interface B {}
class BImpl implements B {}
interface C {}
class CImpl implements C {}
...
class X {}
class A extends X implements B, C, ...
最後に、継承するクラスがたくさんある場合もありますが、どれも定義されていません。これは少し複雑ですが、 委任 を使用することで実行できます。委任により、クラスA
は他のクラスB
のふりをすることができますが、A
の呼び出しはB
で定義された何らかのパブリックメソッドを呼び出し、実際にB
型のオブジェクトへの呼び出しを委任し、結果が返されます。これにより、クラスA
がFat class
と呼ばれるものになります
これはどのように役立ちますか?
まあそれは簡単です。使用する外部クラス内のパブリックメソッドと、作成する新しいクラス内のメソッドを指定するインターフェイスを作成し、そのインターフェイスを新しいクラスに実装します。紛らわしいと思われるかもしれませんので、もっと詳しく説明しましょう。
最初に、次の外部クラスB
、C
、D
、...、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
}
最後に、インターフェイスAImpl
を実装するクラスA
を作成します。
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
がなかったのですか?これはreduce カップリング 。 A
を使用するクラスが、クラスA
に過度に依存する必要はありません(クラスは大きく変化する傾向があるため)。むしろ、インターフェイスA
内で指定されたプロミスに依存します。
Javaでは、複数のクラスを拡張できません。
CクラスがAクラスとBクラスを拡張していると仮定しましょう。次に、AクラスとBクラスに同じ名前のメソッドがある場合(例:method1())。コードを考慮してください:
C obj1 = new C();
obj1.method1();
-ここでは、JVMはアクセスする必要があるメソッドを認識しません。 AクラスとBクラスの両方にこのメソッドがあるためです。したがって、JVMをジレンマに陥れているため、Javaから多重継承が削除されるのはそのためです。前述のように、複数のクラスを実装するとこの問題が解決します。
これがお役に立てば幸いです。