aに a を追加できないようにするジェネリックの get および put ルールについて読みました。Banana
List<? extends Fruit>
public abstract class Fruit { }
public class Banana extends Fruit { }
public class Apple extends Fruit { }
List<? extends Fruit> lst = new ArrayList<>();
lst.add(new Banana()); // Compile error "The method add(capture#6-of ? extends Fruit) in the type List<capture#6-of ? extends Fruit> is not applicable for the arguments (Banana)"
コンパイルエラーがなければ、次のことができることを理解しています。
List<? extends Fruit> lst = new ArrayList<>();
lst.add(new Banana());
lst.add(new Apple());
同じリストに異なるオブジェクトタイプを取得するため、これは間違っているように聞こえます(@Tom Hawtinsによる理由を説明する回答を見て、彼を信じました:)(ただし、リンクが見つかりません))。
ただし、以下を実装する場合:
public class ListFruit implements List<Fruit> {
List<Fruit> list;
public ListFruit() {
list = new ArrayList<>();
}
@Override public int size() { return list.size(); }
// All delegates of "list"
@Override public List<Fruit> subList(int fromIndex, int toIndex) { return list.subList(fromIndex, toIndex); }
}
そして、次のようにします。
ListFruit lst = new ListFruit();
lst.add(new Banana());
lst.add(new Apple());
for (Fruit fruit : lst)
System.out.println(fruit.getClass().getName());
コンパイル エラーは発生せず、次の (予期される) 出力が得られます。
Banana
Apple
そうすることで契約に違反しますか?または、保護を回避していて、それを行うべきではありませんか?