ジェネリクスあれこれ
今日少し話題になったジェネリクスについて少しまとめる。
この内容は他のブログでも詳しく紹介してるけど個人的な復習の意味も込めて。
まずクラスBとこれを継承したクラスDがあるとする。
class B{} class D extends B{}
親クラスは子クラスの参照を保持できる。Java(OOPL全般?)の基本ですね。
B b = new D();
ジェネリクスでこれをやるとどうなるか。ジェネリクスで同様の描き方は通用しない。
List<B> blist = new ArrayList<D>(); //コンパイルエラー
これでは余りにも役に立たないのでJavaはワイルドカードを用いて上界を指定する書き方ができる。
List<? extends B> blist2 = new ArrayList<D>(); //これはいける
これでめでたしめでたし、となるがワイルドカードを用いてジェネリクスを記述すると以下のような制約が課される。
List<? extend B> blist2 = new ArrayList<D>(); blist2.add(new D()); //できない blist2.add(new B()); //できない
上記のように< ? extends 何とか> という記述をすると
要素を追加できない(追加できるのはnullだけ)。
このエラーにコーディング中に遭遇すると何でやねん!!と思うかもしれないが、
blist2.add(new B())が出来ない理由を考えると、これは"List"がList
同様にblist2.add(new B())も出来ないのはBを継承したクラスがジェネリクスに与えれる可能性があるからと考えられる。
superを用いた下界の記述したときにもまた別の制約が課されるが、superはあんまりお目にかからないので省略