Variance in Java
JDK 5.0においてはparametric polymorphism (aka generics)が採用され,型変数を使って定義したクラス C
は C
とか書くことでインスタンシエートできる(型の消去に基づく).ここで元々のinclusion polymorphism (aka subtyping)との関連がかなり複雑になっているようだ.
型変数を使って定義したクラス定義一つから,(τをメタな型変数として) C<τ>
と書くとinvariant, C<? extends τ>
と書くとcovariant, C<? super τ>
と書くとcontravariantな型が得られる... と書こうと思ったんだが,そもそも C<? extends τ>
の存在意義は σ <: τ なる型に対し C<σ>
<: C<? extends τ>
となることである.こういうのを何て呼ぶんだろう?
The Java Programming Language の著者Ken Arnoldの意見は「Genericsなんて複雑な割にご利益が少ない.採用すべきでなかった.みんな今までgenericsなしでやってきたじゃん」だそうな.
- http://weblogs.java.net/blog/arnold/archive/2005/06/generics_consid_1.html Ken Arnold's Blog: Generics Considered Harmful
私はコンテナが使いやすくなったことだけでもgenericsいいと思うけどね.
ArrayList<? super Number> ausn; ArrayList<? extends Number> auen; ArrayList<Object> ao = new ArrayList<Object>(); ArrayList<Number> an = new ArrayList<Number>(); ArrayList<Integer> ai = new ArrayList<Integer>(); ausn = ao; ausn = an; // ausn = ai; // invalid // auen = ao; // invalid auen = an; auen = ai;
// co/contra-variance ArrayList<? super Object> auso = null; // array of unknown which is superclass of Object ArrayList<? extends Object> aueo = null; ArrayList<? super Integer> ausi = null; ArrayList<? extends Integer> auei = null; // contravariance! ausi = auso; // auso = ausi; // invalid // covariance! // auei = aueo; // invalid aueo = auei;
><