26462


開発中に気になったのですが何故Javaは多重継承が許されていないのですか？  
調べてみると

> メソッド名が重複した場合の処置など、多重継承が様々な問題を引き起こしやすいからです

とのことですが、それなら多重継承しているクラスは必ずオーバーライドすればいいと思ったのですが。  
また、`super.method()`のようにする時も多重継承しているなら`super.AClass.method()`のようにすれば困ることがあまりないと思います。  
(一応言っておきますがinterfaceの多重継承ではありません。どちらもクラスの時です)


CC BY-SA 3.0
2016-06-05T00:00:58.160
25461
2016-06-20T02:07:16.707
15185
question
java java8
何故Javaでは多重継承は許されていないのか


言語設計時の選択として、単純さ(Simple)を選んだ結果でしょう。Javaの生みの親 James
Gosling氏による、1995年発行のWhitePaper ["Java: an
Overview"](http://www.cs.dartmouth.edu/~mckeeman/cs118/references/OriginalJavaWhitepaper.pdf)
より引用します。

> **Simple**  
>  JAVA omits many rarely used, poorly understood, confusing features of C++
> that in our experience bring more grief than benefit. This primarily
> consists of operator overloading (although it does have method overloading),
> multiple inheritance, and extensive automatic coercions.

* * *

多重継承(multiple
inheritance)が意味する範囲は広く、「状態(state)の多重継承」、「実装(implementation)の多重継承」、「型(type)の多重継承」に分類できます。公式The
Java Tutorials, [Multiple Inheritance of State, Implementation, and
Type](https://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html)
でも言及されている通り：

  * 状態(state)の多重継承：言語仕様上の選択としてサポートしない
  * 実装(implementation)の多重継承：Java8で導入されたデフォルトメソッド(default method)でサポート
  * 型(type)の多重継承：インターフェイス(interface)継承でサポート

同WhitePaperで言及されるC++言語の場合、既定動作では「状態(state)の多重継承」により親クラスの状態が複数存在する振る舞いになります。これを回避する機構として仮想継承(virtual
inheritance)という言語機能をオプション提供しますが、比較的複雑で難解な機能です。C++ではプログラマに選択の自由度を与えますが、複雑で理解を難しくしているのも事実です。

[code]

    // C++言語における「状態(state)の多重継承」
    
    class B { int m1; };
    // クラスD1,D2ともにクラスBを継承
    class D1 : public B { ... };
    class D2 : public B { ... };
    
    // D1,D2を多重継承したクラスXのインスタンスには
    // 親クラスBのインスタンスが 2 つ含まれる。
    // つまりm1変数という「状態」が2つ同時に存在する。
    class X : public D1, D2 {};
    
[/code]

Java言語では、プログラマにこのような難しい選択をさせないという思想になっています。


CC BY-SA 3.0
2016-06-05T02:12:28.580
26462
2016-06-05T02:40:57.313
2016-06-05T02:40:57.313
49
49
25461
answer


多重継承には、菱型継承問題（diamond problem）という有名な問題があります。  
<https://ja.wikipedia.org/wiki/%E8%8F%B1%E5%BD%A2%E7%B6%99%E6%89%BF%E5%95%8F%E9%A1%8C>

例えば、クラスDがBとCを継承しており、BとCが共通のAを継承しているような菱型の継承関係が多重継承では発生しえますが、この時にDに対してメソッド呼び出しがあった場合にどういった優先順位でメソッドを呼び出すのか、という問題です。Aで定義された`aMethod()`がBとCでオーバーライドされていた場合、Dに対して`aMethod()`が呼び出されたら、BとCのどちらを優先して呼び出せばいいでしょうか？

多重継承を持つ多くのプログラミング言語では、多重継承時のメソッド呼び出しに対して何らかの方法で優先順位を決めることで、この菱形継承問題を解決しています。しかし、言語によってルールは様々である上に、たとえルールが明確であったとしても、実用的なプログラムにおいて継承の階層が何重にもなって複雑化した場合には、継承の経路のどういった順番でメソッド呼び出しが行なわれるかを直感的にすぐ理解することは非常に難しくなるでしょう。

Javaでは（そして多くのモダンなプログラミング言語では）、言語設計としてこうした多重継承の問題による弊害が、それを導入した場合のメリットよりも大きいと判断して、単一継承を採用しています。

yohjpさんが回答されているJavaが「単純さを選んだ」ということを、もう少し具体的に説明するとこのようになります。


CC BY-SA 3.0
2016-06-07T10:06:11.987
26540
2016-06-07T10:06:11.987
244
25461
answer