0

aに a を追加できないようにするジェネリックの get および put ルールについて読みました。BananaList<? 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

そうすることで契約に違反しますか?または、保護を回避していて、それを行うべきではありませんか?

4

3 に答える 3