在下面的代码中,如果我们在base中使用泛型,然后在diff接口中扩展它,kotlin不尊重基接口的泛型。
为什么会这样?
在底部我没有使用" In "或";out"但是默认情况下扩展的接口仍然会变成"out"
interface FeaturedCardAdapterContract {
interface View {
fun onCreate()
}
interface SubPresenter<V : View> {
fun onBind(v: V)
}
}
interface FeaturedTestAdapterContract {
interface View : FeaturedCardAdapterContract.View
interface Presenter : FeaturedCardAdapterContract.SubPresenter<View>
}
fun main() {
val featureImpl1: FeaturedTestAdapterContract.Presenter = object : FeaturedTestAdapterContract.Presenter {
override fun onBind(v: FeaturedTestAdapterContract.View) {
}
}
val featureImpl2: FeaturedTestAdapterContract.Presenter = object : FeaturedTestAdapterContract.Presenter {
override fun onBind(v: FeaturedTestAdapterContract.View) {
}
}
//Works but i won't be able to consume it in onBind bcz kotlin assumed it as "out"
val interfaceArray: Array<FeaturedCardAdapterContract.SubPresenter<out FeaturedCardAdapterContract.View>> = arrayOf(featureImpl1, featureImpl2)
//Dosen't Work-bcz kotlin assumes the type of featureImpl1 is FeaturedCardAdapterContract.SubPresenter<out FeaturedCardAdapterContract.View> ,Why?
val interfaceArray: Array<FeaturedCardAdapterContract.SubPresenter<FeaturedCardAdapterContract.View>> = arrayOf(featureImpl1, featureImpl2)
//Works but,Same as 1st method
val interfaceArray: Array<FeaturedCardAdapterContract.SubPresenter<*>> = arrayOf(featureImpl1, featureImpl2)
for (featureImpl in interfaceArray) {
//Won't work bcz of "out"
featureImpl.onBind(object : FeaturedCardAdapterContract.View {
override fun onCreate() {
//
}
})
}
}
将接口重命名为Processor
,Animal
和Dog
,您将看到为什么编译器对类型是正确的,而您试图做的事情没有意义。
重命名:
interface Animal // FeaturedCardAdapterContract.View
interface Processor<A: Animal> { // FeaturedCardAdapterContract.SubPresenter<V>
fun process(animal: A) // onBind
}
interface Dog: Animal // FeaturedTestAdapterContract.View
interface DogProcessor: Processor<Dog> // FeaturedTestAdapterContract.Presenter
在main
中,您正在创建一个包含2个DogProcessor
s的数组:
val processorImpl1 = object: DogProcessor {
override fun process(animal: Dog) {
}
}
val processorImpl2 = object: DogProcessor {
override fun process(animal: Dog) {
}
}
val array = arrayOf(processorImpl1, processorImpl2)
然后你试着循环它,让它们每个处理一个动物:
val array = arrayOf(processorImpl1, processorImpl2)
for (processor in array) {
processor.process(object: Animal {
})
}
无论你如何改变array
的类型,这显然是行不通的。数组中的处理器专门处理狗,而不是一般的动物。你可以简单地通过给它狗而不是动物来实现这一点,或者在你的情况下:
val interfaceArray = arrayOf(featureImpl1, featureImpl2)
for (featureImpl in interfaceArray) {
featureImpl.onBind(object : FeaturedTestAdapterContract.View {
override fun onCreate() {
//
}
})
}
注意,数组的类型可以更改为Array<Processor<out Animal>>
——一个只生成动物的处理器数组。这是因为狗的生产者是一种动物的生产者。参见:PECS。然而,由于您想在这里调用process
(onBind
),您希望处理器接收,或者消耗动物,而不是生产动物。因此,Array<Processor<out Animal>>
不是您想要的。
为了澄清,您已经将featureImpl1
定义为FeaturedTestAdapterContract.Presenter
,因此它是FeaturedCardAdapterContract.SubPresenter<FeaturedTestAdapterContract.View>
。
注意"Test"视图,而不是"卡片"。一个。这是您自己对Presenter
的定义——您在定义中使用的View
是测试视图FeaturedTestAdapterContract.View
的快捷方式,而不是卡视图FeaturedCardAdapterContract.View
:
val featureImpl1: FeaturedTestAdapterContract.Presenter = object : FeaturedTestAdapterContract.Presenter {
// only wants test views here
override fun onBind(v: FeaturedTestAdapterContract.View) {
}
现在检查这部分:
不能工作,因为"out">
featureImpl.onBind(object : FeaturedCardAdapterContract.View { //... })
让我们暂时忘记out
。您已经定义了featureImpl1
,因此它只接受将绑定到特定的FeaturedTestAdapterContract.View
。但这里你试图传递一个cardviewFeaturedCardAdapterContract.View
,它不是一个测试视图。如果允许这样做,featureImpl1
的主体就会失败,因为它被赋予的对象不是FeaturedTestAdapterContract.View
类型,甚至不是它的子类型。
//Works but i won't be able to consume it in onBind bcz kotlin assumed it as "out" val interfaceArray: Array<FeaturedCardAdapterContract.SubPresenter<out FeaturedCardAdapterContract.View>> = arrayOf(featureImpl1, featureImpl2)
Kotlin在这里没有做任何假设,你自己标记out
。但是由于我上面的解释,你必须写出来是很正常的。
我们刚刚看到featureImpl1
是SubPresenter<FeaturedTestAdapterContract.View>
。它不能被分配给SubPresenter<FeaturedCardAdapterContract.View>
(没有out),因为这意味着它需要接受比实际更多的类型。