Я изо всех сил пытаюсь понять и / или заставить дженерики и полиморфизм Kotlin работать на меня.Рассмотрим этот код:
class Item<T: BaseAttributes> {
var id: Long = -1L
lateinit var type: String
lateinit var attributes: T
}
open class BaseAttributes {
lateinit var createdAt: String
lateinit var updatedAt: String
}
open class BaseResponseList<T : BaseAttributes> {
lateinit var items: List<Item<T>> // the collection of items fetched from an API
}
class FruitAttributes(val id: Long, val color: String /* ... */) : BaseAttributes()
class FruitResponseList: BaseResponseList<FruitAttributes>()
// base service for all types of items
interface ApiService {
fun getItems(): BaseResponseList<BaseAttributes>
// fun getItemById(itemId: Long): BaseResponse<BaseAttributes>
/* other CRUD functions here ... */
}
// service for fruits
interface FruitService: ApiService {
override fun getItems(): FruitResponseList // get fruit items
}
Я озадачен этой ошибкой компилятора, которая предполагает, что FruitResponseList
не является подтипом параметризованного базового класса (BaseResponseList<FruitAttributes>
):
Return type of 'getItems' is not a subtype of the return type of the overridden member 'public abstract fun getItems(): BaseResponseList<BaseAttributes> defined in ApiService'
Я пытаюсь использовать ковариацию сайта объявлений в BaseAttributes, чтобы сообщить компилятору о моем намерении, что FruitResponseList является подклассом базового списка ответов, как это:
open class BaseResponseList<out T : BaseAttributes> {
lateinit var items: List<Item<T>> // the collection of items fetched from an API
}
приводит к этой ошибке:
Type parameter T is declared as 'out' but occurs in 'invariant' position in type List<Item<T>>
Как мне получить отношение типа-подтипа между списками ответов Fruit & Base?
Контекст
Я реализуюсетевой код для выполнения операций CRUD с API, который основан на формате JSON API spec , поэтому я создал атрибуты и классы данных (Item
) для представления объектов ответа json.
Моя цель - уменьшить количество дублирующегося кода, чтобы мне приходилось писать декларации службы API только один раз для каждой сущности в моем приложении (фрукты, поставщики, покупатели и т. Д.).Я также хочу избежать написания дублированных / стандартных реализаций уровней хранилища данных для каждой сущности в моем приложении (в контексте чистой архитектуры).Я должен иметь возможность просто указать специфичные для бизнес-сущности типы (модели / сущности) и позволить одной общей реализации выполнять выборку сетевых данных.
Я думал, что для достижения этого имеет смысл использовать дженерики и наследование.В этом конкретном примере идея заключается в том, что GET для конкретного фрукта будет возвращать список ответов фрукта, который является подтипом базового списка ответов.Буду очень признателен за любые указания по этому, или альтернативные подходы к этой проблеме