kip*_*ip2 5 generics polymorphism android kotlin retrofit
我正在努力理解和/或让 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
}
Run Code Online (Sandbox Code Playgroud)
我被这个编译器错误难住了,它表明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
}
Run Code Online (Sandbox Code Playgroud)
导致这个错误:
Type parameter T is declared as 'out' but occurs in 'invariant' position in type List<Item<T>>
如何实现 Fruit 和 Base 响应列表之间的类型-子类型关系?
我正在实现网络代码以针对基于JSON API 规范格式的 API 执行 CRUD 操作,因此我创建了属性和数据 ( Item) 类来表示 json 响应对象。
我的目标是减少重复代码的数量,这样我只需为应用程序中的每个实体(水果、供应商、买家等)编写一次 API 服务声明。我还想避免为我的应用程序中的每个实体编写数据存储库层的重复/样板实现(在干净架构的上下文中)。我应该能够只指定特定于业务实体的类型(模型/实体),并让一个通用实现完成获取网络数据的工作。
我认为使用泛型和继承来实现这一点是有意义的。在此特定示例中,想法是特定于水果的 GET 将返回水果响应列表,该列表是基本响应列表的子类型。将非常感谢任何有关此问题的指导或解决此问题的替代方法
我被这个编译器错误难住了,它表明
FruitResponseList不是参数化基类(BaseResponseList<FruitAttributes>)的子类型:
它是 的子类型BaseResponseList<FruitAttributes>,而不是 的子类型BaseResponseList<BaseAttributes>。
我尝试在 BaseAttributes 中使用声明站点协方差来告诉编译器我的意图,FruitResponseList 是基本响应列表的子类,如下所示:...
这可能是一个正确的方法,但问题是它Item不是协变的(而且不可能是因为attributesis avar并且它的 setter 带有一个T参数)。如果Item可以修改以避免这种情况,那就太好了。
另一种方法是将类型参数添加到ApiService:
// base service for all types of items
interface ApiService<T: BaseAttributes> {
fun getItems(): BaseResponseList<T>
// fun getItemById(itemId: Long): BaseResponse<T>
/* other CRUD functions here ... */
}
// service for fruits
interface FruitService: ApiService<FruitAttributes> {
override fun getItems(): FruitResponseList // get fruit items
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
993 次 |
| 最近记录: |