Kotlin 通用自动转换为"out"



在下面的代码中,如果我们在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,AnimalDog,您将看到为什么编译器对类型是正确的,而您试图做的事情没有意义。

重命名:

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个DogProcessors的数组:

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。但是由于我上面的解释,你必须写出来是很正常的。

我们刚刚看到featureImpl1SubPresenter<FeaturedTestAdapterContract.View>。它不能被分配给SubPresenter<FeaturedCardAdapterContract.View>(没有out),因为这意味着它需要接受比实际更多的类型。

相关内容

最新更新