いろいろガンガンいこうぜ。体も大事に

普段はJavaでAndroidアプリ開発しているプログラマーのブログです。

ジェネリクス(総称型)について その1

型とか継承とかジェネリクスの話。 特にジェネリクスは理解していると思っていたのですが,理解が甘かったです。

package com.mrstar.practice_generics;

public class Super {
}

このSuperというクラスと,

package com.mrstar.practice_generics;

public class Sub extends Super {
}

Superを継承したSubというクラスがあるとします。

Super object0 = new Super();
Sub object1 = new Sub();

任意の型の変数に,その型のインスタンスを代入することは当然できます。

Super object2 = new Sub();
// Sub object3 = new Super(); コンパイルエラー

スーパークラスの変数に,サブクラスのインスタンスを代入することは可能だけれども,サブクラスの変数にスーパークラスインスタンスは代入することができません。

ArrayListを使ってみます。

ArrayList<Super> list0 = new ArrayList<Super>();
list0.add(new Super());
list0.add(new Sub());

ArrayList <Super>の変数にArrayList<Super>型のインスタンスを代入します。 それに対して,Super型のインスタンスや,Sub型のインスタンスをaddします。

ArrayList<Sub> list1 = new ArrayList<Sub>();
//list1.add(new Super()); コンパイルエラー
list1.add(new Sub());

ArrayList<Sub>の変数にArrayList<Sub>型のインスタンスを代入します。 それに対してSub型のインスタンスはaddできますが,当然Super型のインスタンスはaddできません。

さて,ここからです。

ArrayList<Super> list = new ArrayList<Sub>(): // これはコンパイルが通る?コンパイルエラー?

がっつり迷ってしまいました。
ていうか分かりませんでした。

コンパイルエラーでした。

仮にこれがコンパイルエラーになら無い場合を考えてみます。
その場合はArrayLlist<Sub>型のインスタンスArrayList<Super>型の変数listに入っています。

ArrayList<Super>型の変数listは,Super型のインスタンスやSub型以外のSuper型を継承したインスタンスもaddできなくてはいけません。 ですが,ArrayList<Sub>のインスタンスは,Super型のインスタンスもSub型以外のSuper型を継承したインスタンスもaddはできません。 矛盾が生じますね。

そもそもスーパークラスの変数にサブクラスのインスタンスは代入出来ますが,型パラメータですからね,今回の問題は。

分かったつもりになっていました。
ジェネリクスについてはもっと勉強しないといけません。