ArrayList конфликтов абстрактных и вложенных классов - PullRequest
1 голос
/ 19 апреля 2019

У меня есть адаптер:

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 ]

3 голосов
/ 19 апреля 2019

Поскольку List является ковариантным (определяется как List<out T>), поэтому List<PhotoAdapter.PhotoItem> является подтипом List<AbstractItem>.Но MutableList и ArrayList являются инвариантами, что означает, что ArrayList<PhotoAdapter.PhotoItem> не является подтипом (или супертипом) ArrayList<AbstractItem>.

См. https://kotlinlang.org/docs/reference/generics.html#variance для подробного объяснения почему (Iне думайте, что здесь есть смысл копировать его).

1 голос
/ 19 апреля 2019

В Java это можно решить, объявив

void addItems(ArrayList<? extends AbstractItem> list)

Я не знаю, каков для этого синтаксис kotlin.

...