ジェネリクス(総称型)について その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はできません。 矛盾が生じますね。
そもそもスーパークラスの変数にサブクラスのインスタンスは代入出来ますが,型パラメータですからね,今回の問題は。
分かったつもりになっていました。
ジェネリクスについてはもっと勉強しないといけません。