ご覧のとおり、コードには 2 つのエラーがあります。List<Ref<? extends Thing>>
1 つ目は、その型が のスーパータイプであると信じることですList<Ref<Thing>>
。Thing
likeのサブクラスを作成した場合DerivedThing
、 のインスタンスRef<DerivedThing>
を のリストに追加することはできませんList<Ref<Thing>>
。
List<Ref<Thing>> refs = new ArrayList<Ref<Thing>>();
refs.add(new Ref<Thing>()); // OK.
refs.add(new Ref<DerivedThing>()); // Error!
ただし、これを次のように置き換えればList<Ref<? extends Thing>>
、クラスの問題はなくなりますDerivedThing
。
List<Ref<? extends Thing>> refs = new ArrayList<Ref<? extends Thing>>();
refs.add(new Ref<Thing>()); // Still OK.
refs.add(new Ref<DerivedThing>()); // Now OK!
したがって、コンパイラが引数としてList<Ref<? extends Thing>>
関数にの値を渡すことを許可した場合、関数は無効な項目をリストに追加することができます。List<Ref<? extends Thing>>
<? extends Thing>
2 番目のエラーは、 の基本型 (または消去型)がSuperThing
ではなく であると考えることThing
です。ここでは、 とその派生クラスのコレクションではなく、 とその派生クラスで<? extends Thing>
構成される型のコレクションを指定します。したがって、次のように書くことができます。Thing
SuperThing
List<Ref<? extends Thing>> refs = new ArrayList<Ref<? extends Thing>>();
refs.add(new Ref<Thing>());
List<Thing> objectList = refsToObjects(refs);
または、SuperThing
消去タイプとして:
List<Ref<? extends SuperThing>> refs = new ArrayList<Ref<? extends SuperThing>>();
refs.add(new Ref<Thing>());
List<SuperThing> objectList = refsToObjects(refs);
List<SuperThing>
ただし、は のスーパークラスではないため、両方の組み合わせではありませList<Thing>.
ん。したがって、上記の解決策のいずれかを使用するか、出発点として保持したい場合はwrm の解決策を使用してください。Ref<Thing>
List<Ref<? extends SuperThing>>
List<Ref<Thing>>
個人的には、ポリモーフィズムを最大限に活用し、常にSuperThing
;からすべてを参照することを好みます。Thing
またはRef<Thing>
オブジェクトを作成する場合でも。たとえば、 type のパラメーターをT
のコンストラクターに追加すると、次のようになりRef()
ます。
List<Ref<SuperThing>> refs = new ArrayList<Ref<SuperThing>>();
refs.add(new Ref<SuperThing>(new Thing()));
List<SuperThing> objectList = refsToObjects(refs);
のコンストラクタでtypeのオブジェクトを typeThing
の参照に渡していることに注意してください。階層のスーパークラスをすべての派生オブジェクトの参照として使用することで、すべてのコーディングがはるかに簡単になります。OOP は、ほとんどすべてのオブジェクトをそのスーパークラスのみを介して表示することを選択した場合に非常にうまく機能し、非常に簡単に機能し、これはジェネリックの使用にまで及びます。SuperThing
Ref()