抽象和嵌套类的ArrayList冲突

时间:2019-04-19 09:44:51

标签: java list arraylist kotlin casting

我有一个适配器:

class PhotoAdapter : RecyclerView.Adapter<PhotoAdapter.AbstractViewHolder>() {

    fun addItems(list: ArrayList<AbstractItem>) {
        val position = items.size
        items.addAll(list)
        notifyItemRangeInserted(position, list.size)
    }

    abstract class AbstractItem(
        open val id: Int
    )

    class PhotoItem(
        override val id: Int,
        val url: String?
    ) : AbstractItem(id)

    ...
}

和使用它的片段:

val adapter = PhotoAdapter()
val list: ArrayList<PhotoAdapter.PhotoItem> = ArrayList(emptyList<PhotoAdapter.PhotoItem>())
adapter.addItems(list)

但是尽管PhotoItem嵌套在AbstractItem中,但我无法编译:

enter image description here

如果我将ArrayList中的addItems()更改为简单的List,则会编译:

fun addItems(list: List<AbstractItem>) {
...

也许类型转换也可以,但是我没有检查。

enter image description here

问题是,为什么实现(ArrayList)和接口(List)在嵌套类上有不同的观点?

更新

我改写了Java,这会更加清楚。

public class Adapter extends RecyclerView.Adapter<Adapter.AbstractViewHolder> {

    private ArrayList<AbstractItem> items;

    public void addItems(ArrayList<AbstractItem> list) {
        int position = items.size();
        items.addAll(list);
        notifyItemRangeInserted(position, list.size());
    }

    abstract class AbstractViewHolder extends RecyclerView.ViewHolder {

        public AbstractViewHolder(@NonNull View itemView) {
            super(itemView);
        }
    }

    public abstract class AbstractItem {
        int id;
    }

    public class PhotoItem extends AbstractItem {
        int id;
        String url;
    }
}

public class Example {

    void init() {
        ArrayList<Adapter.PhotoItem> list = new ArrayList<>();
        Adapter adapter = new Adapter();
        adapter.addItems(list);
    }
}

enter image description here

2 个答案:

答案 0 :(得分:3)

因为List是协变的(定义为List<out T>),所以List<PhotoAdapter.PhotoItem>List<AbstractItem>的子类型。但是MutableListArrayList是不变的,这意味着ArrayList<PhotoAdapter.PhotoItem>不是ArrayList<AbstractItem>的子类型(或超类型)。

有关原因的详细说明,请参见https://kotlinlang.org/docs/reference/generics.html#variance(我认为在这里没有太多重复之处)。

答案 1 :(得分:1)

在Java中,可以通过声明来解决

void addItems(ArrayList<? extends AbstractItem> list)

我不知道什么是kotlin语法。