1. ホーム
  2. java

[解決済み] Java : A が B を拡張し、B が Object を拡張する場合、多重継承となるか?

2022-02-07 23:31:40

質問

先ほど面接を受けたのですが、質問を受けました。

面接官 - Javaは多重継承をサポートしていますか?

- いいえ

インタビュアー - Java の各クラスはクラス Object を継承しており(クラス Object を除く)、あるクラスを外部で拡張すると

Class A extends B{
  // some code here
}

とすると、クラスAはクラスBとクラスObjectを拡張していることになり、多重継承と言えます。では、なぜJavaは多重継承をサポートしていないと言えるのでしょうか?

- 実はクラスBはクラスObjectを継承しているので、クラスAでクラスBを継承すると、クラスAは間接的にクラスObjectを継承することになるのです。これは多段階継承であって、多重継承ではありません。

しかし、私の答えは彼を納得させるものではなかった。

私の答えは正しいのでしょうか?それともどこが間違っているのでしょうか? 実際に内部で何が起こっているのでしょうか?

解決方法は?

<ブロッククオート

私の答えは正しいのでしょうか?

はい、ほとんど、そして確かにあなたが説明した文脈ではそうです。これは多重継承ではありません。

おっしゃる通り、多段で単一継承です。

これは多重継承です。これは、互いに何の関係もない2つ以上のベースから継承することで、無関係なラインから、あるいは以前に分岐したラインから継承することになります(Javaでは Object は常にベースであるため、後者になる)。

<イグ

(画像引用元 http://yuml.me in "scruffy" モード)

<ブロッククオート

内部的にはどうなっているのか?

おっしゃるとおりです。複数のレベルがあります。コンパイラがインスタンスのメンバを解決するとき。

obj.member

...この処理は obj (この場合クラスであり、例えば ClassB があります。 member を直接提供するか、継承によって持っているためです。実行時に、JVMは member が実際に持っているものです。


上記で「ほとんど」と言ったのは、Javaにはインターフェースがあり、Java 8からはインターフェースに「デフォルトメソッド」が追加されたからです。これは物事を少し複雑にしますが、レベルについてのあなたの答えは、あなたが面接官から言われたことの文脈で正しいです Object , ClassA および ClassB .

インターフェイスは、Javaでは常に2つの異なる型と "is"の関係を持つことを可能にしてきました。クラス型はそれを継承し、インターフェース型はそのクラスが持ついくつかの型のうちのどれかとなります。 インプリメント . デフォルトメソッドのないインターフェースは現実的には多重継承ではありませんが(クラスが実装を提供しなければならない)、一つのクラスが無関係な型木から複数の "is a" の関係を持つことを可能にしました。 (私は学者ではないので、学者は学術的に多重継承を提供すると主張するかもしれません。)。

Java 8では、インタフェースが定義するメソッドのデフォルト実装を提供できるようになり、実用レベルでも境界が曖昧になりました。もう少し詳しく見てみましょう。

例えば ClassA :

class ClassA {
    void doSomething() {
        // Code here
    }
}

Interface1 :

interface Interface1 {
    default void doSomethingElse() { // Requires Java 8
        // Code here
    }
}

そして最後に ClassB :

class ClassB extends ClassA implements Interface1 {
}

ClassB の実装を継承しています。 doSomething から ClassA . しかし、それは また の "default"バージョンを取得します。 doSomethingElse から Interface1 . には実装していません。 ClassB しかし ClassB は抽象的ではありません。 doSomethingElse . これは インターフェース . そこでは "inherits" ではなく "gets" という単語を使いましたが、これは見た目が ロット デフォルトのメソッドを継承しているようなものです。

これは基本的に多重継承のquot;light"(quot;light beer"のように)である。これは、真の多重継承が抱える以下のような問題を回避するものです。

  • のタイプはどうすればよいのでしょうか? super であるか?(Java 8の答えです。 ClassA )
  • コンストラクタの実行順序は?(Java 8の答え。単一行のコンストラクター連鎖で、インターフェースにはコンストラクターがありません)。
  • 複数回継承するコンストラクターは、複数回実行するのですか? (Java 8の答えです。コンストラクタを複数回継承することはできません。インターフェイスにはありません)。
  • 同じシグネチャを持つメソッドを複数継承した場合はどうなりますか?(Java 8の答え。ベースクラスの実装は、複数のインターフェースのデフォルトメソッドを オーバーライドすることができます。コンパイル時に異なるインターフェイスから同じシグネチャのデフォルトメソッドが複数ある場合は、コンパイル時のエラーになります。クラスを再コンパイルしないままインターフェースが変更され、実行時にそのような状況が発生した場合は、実行時 IncompatibleClassChangeError 例外として、競合するデフォルトメソッドをリストアップします)。