クラスをくっつけ……られない!
質問:2つのスーパークラスから1つのサブクラスを作ることができますか?
解答:できません。
スーパークラスを複数使って1つのサブクラスを作ることを「多重継承」と言います。
多重継承することで、複数のクラスの機能を組み合わせたすごいクラスを作ることができます。
……が、実はこの多重継承、できません。
/**
* 普通のクラスA。
* フィールドをひとつ持ちます。
*/
class SuperA
{
int data;
}
/**
* 普通のクラスB。
* フィールドをひとつ持ちます。
*/
class SuperB
{
int data;
}
/**
* SuperAクラスとSuperBクラスから継承した、サブクラス。
* ……こんなクラスは作れません!
*/
class MultipleInheritSub extends SuperA, SuperB
{
}
// コンパイルエラー:
// MultipleInheritSubRunner.java:25: '{' がありません。
// class MultipleInheritSub extends SuperA, SuperB
// MultipleInheritSubRunner.java /** * 普通のクラスA。 * フィールドをひとつ持ちます。 */ class SuperA { int data; } /** * 普通のクラスB。 * フィールドをひとつ持ちます。 */ class SuperB { int data; } /** * SuperAクラスとSuperBクラスから継承した、サブクラス。 * ……こんなクラスは作れません! */ class MultipleInheritSub extends SuperA, SuperB { } // コンパイルエラー: // MultipleInheritSubRunner.java:25: '{' がありません。 // class MultipleInheritSub extends SuperA, SuperB
まず、HasOneMethodSuper3クラスを用意します。
* 普通のクラス。
* メソッド1つ持ちます。
* (HasOneMethodSuperクラスと同じです)
*/
class HasOneMethodSuper3
{
/**
* 自クラスの名前を出力するメソッドです。
*/
void printMyName()
{
System.out.println( "HasOneMethodSuper3" );
}
}
/** * 普通のクラス。 * メソッド1つ持ちます。 * (HasOneMethodSuperクラスと同じです) */ class HasOneMethodSuper3 { /** * 自クラスの名前を出力するメソッドです。 */ void printMyName() { System.out.println( "HasOneMethodSuper3" ); } }
MultipleInheritSubクラスは、SuperAクラスとSuperBクラスをスーパークラスに持つサブクラスです。
でも、こんなクラスを作ろうとするとコンパイルエラーになってしまいます。
* SuperAクラスとSuperBクラスから継承した、サブクラス。
* ……こんなクラスは作れません!
*/
class MultipleInheritSub extends SuperA, SuperB
{
}
// コンパイルエラー:
// MultipleInheritSubRunner.java:25: '{' がありません。
// class MultipleInheritSub extends SuperA, SuperB
/** * SuperAクラスとSuperBクラスから継承した、サブクラス。 * ……こんなクラスは作れません! */ class MultipleInheritSub extends SuperA, SuperB { } // コンパイルエラー: // MultipleInheritSubRunner.java:25: '{' がありません。 // class MultipleInheritSub extends SuperA, SuperB
もし作ることができたら、MultipleInheritSubクラスはSuperAクラスとSuperBクラスを組み合わせたクラスになります。
MultipleInheritSubクラスのインスタンスを作ると、SuperAクラスとSuperBクラスのインスタンスが中に作られることになります。
でも作ることができません。なぜできないようになっているのでしょう。
それは、クラスの構造が複雑になるからです。
たとえばこの例だと、SuperAクラスにdataフィールドが、さらにとSuperBクラスにもdataフィールドがあります、つまり両方にdataフィールドがあります。
そのため、サブクラスでdataフィールドを使う場合に「どのスーパークラスのdataフィールドか」ということを指定する必要があります。そうしないと、どっちのdataフィールドを使えばいいのかわからないからです。
多重継承を許すと、クラスの構造が複雑になります。
対して、多重継承できない場合(これを「単一継承」と言います)には、スーパークラスからサブクラスへ枝葉のように伸びていくシンプルな構造になります。
(上がスーパークラス、下がサブクラスになります)
多重継承の例の、クラスEのインスタンスを作ったら、どんなインスタンスが作られるのか想像もできません。そして、各クラスを使う場合には「このクラスのインスタンスの、このフィールド・メソッドを使う」と指定しなければいけなくなり、それはとても複雑なことになります。
対して、単一継承なら複雑なことにはなりません。単一継承の例のクラスDは、インスタンスを作ればクラスCとクラスAのインスタンスを持ちます。ただ単にスーパークラスの方向に内包するだけなのでシンプルです。
このように、単一継承の方が分かりやすいので、多重継承はできないようになっているわけです。