Используя Kotlin, как базовый класс может работать со списком объектов базового класса из своего производного класса, у которого есть список объектов производного класса?

#list #kotlin #inheritance #covariance #declare

Вопрос:

У меня есть настройка, смутно похожая на приведенную ниже (извините, если синтаксис Kotlin/псевдо просто сбивает с толку, дайте мне знать, и я изменю ее).
У меня есть два производных класса, которые содержат списки, элементы которых являются экземплярами производных классов. Где базовые классы списка имеют общие функциональные возможности для списков.
Мне просто было интересно, не глупо ли то, как я это делаю. Есть ли лучший способ использовать списки производных классов (Список, Список) в базовом классе, чем добавлять другое свойство для списка (Списка) и обновлять его в производном классе каждый раз, когда в список вносятся изменения?
Я вроде как хочу объявить свойство списка «элементы» в базовом классе A, а затем переопределить его производным типом в B и C. С помощью методов класса A, использующих приведение списка к общему базовому классу (Списку). Но ты не можешь этого сделать. Ура, надеюсь, это кого-нибудь заинтересует.

 class A {
    val genericItems = List<a>

    methodForGenericItems() {
        do something generic with/to the list
    }
}

class B : A {
    val items = List<b>

    updateItems() {
        update items
        genericItems = items as List<a>
    }

    methodForDerivedItems() {
        do something specific using the list
        call methodForGenericItems()
    }
}

class C : A {
    val items = List<c>

    updateItems() {
        update items
        genericItems = items as List<a>
    }

    methodForDerivedItems() {
        do something specific using the list
        call methodForGenericItems()
    }
}

class a {
    ...
}

class b : a {
    ...
}

class c : a {
    ...
}
 

Комментарии:

1. Жаль, что вы не попытались переписать свой псевдокод в Kotlin, потому что тогда вы обнаружите, что можете достичь этого именно с помощью своего кода: -) Почему вы думаете, что это невозможно?

2. Кроме того, нужно ли вам когда-либо изменять список элементов A непосредственно или только в производных классах? В последнем случае вы действительно можете использовать только одно свойство без какой-либо синхронизации.

3. Ха-ха, я сделал это так, просто почувствовал, что может быть лучший способ сделать это! Казалось немного странным иметь дополнительное свойство, которое совпадает с другим, просто приведенным к его базовому классу, и которое вам нужно обновлять всякий раз, когда вы меняете оригинал

4. В A есть по крайней мере один метод, который изменяет список. Удаляет по определенному индексу. Спасибо за вашу помощь 🙂

Ответ №1:

Это действительно зависит от того, нужно ли нам добавлять новые элементы в базовый класс ( A ) или нет. Если нам нужно это сделать, то у нас проблема, потому A что мы не знаем о дополнительных ограничениях на типы элементов B , введенных C и. Поэтому, что, если мы используем B класс, который работает с b элементами, но одна из функций A добавляет элемент c типа? У нас был бы список b предметов, но содержащий c то, что нарушает безопасность типов. Существует несколько решений этой проблемы, в зависимости от конкретных потребностей.

В вашем случае, похоже, вам нужно только прочитать/удалить элементы A . Это намного проще и не требует никаких обходных путей. Достаточно иметь обычное единственное свойство и просто переопределить его тип в подклассе. Но нам нужно сообщить компилятору, что мы никогда не будем добавлять новые элементы A . Мы можем сделать это вот так:

 open class A {
    open val items: MutableList<out a> = mutableListOf()
}

class B : A() {
    override val items = mutableListOf<b>()
}
 

out a в этом коде означает , что A он может только «вытаскивать» a объекты items , но не может «подталкивать» a объекты к нему.

Комментарии:

1. Большое спасибо, похоже, это именно то, что мне было нужно. Указал мне на эту статью proandroiddev.com/… на случай, если кто-то еще захочет получить дополнительную информацию