好,所以我有三种界面类型。
Movement<T : Animal>
Animal
,带有子接口Cat
,Dog
,Horse
AnimalMovement
运动界面
interface Movement<T : Animal> {
fun moveAnimal(type:T)
}
动物界面
interface Animal {
fun takeSteps()
fun jump()
fun hide()
}
interface Cat : Animal
interface Dog : Animal
动物运动
interface CatMovement : Movement<Cat>
然后我实现CatMovement接口
class CatMovementImpl : CatMovement {
override fun moveAnimal(type: Cat) {
TODO("not implemented")
}
}
问题
fun TestGenerics() {
var catMovement : Movement<Cat> = CatMovementImpl() // this works
var catMovement : Movement<Animal> = CatMovementImpl() // this doesn't?
}
我确定在Java中这两行都可以正常工作。但是,在Kotlin中,第二行无法执行。为什么会这样呢?动物是猫的基本类型,所以这应该行得通吗?
答案 0 :(得分:2)
我不是Kotlin的专家,但这似乎很正常:
当这样声明时:
postProcessAfterInitialization
您可以编写代码:
BeanPostProcessors
但是如果这样分配它:
ImportAware
是允许的,这意味着您的#section1 {
height: 131px;
color: #fff;
background-color: transparent;
margin-top: 246px;
}
应该可以移动狗吗?
答案 1 :(得分:1)
评论中moskito所说的是正确的。
我很确定这在Java中也不起作用。
Movement<Cat>
是 不是Movement<Animal>
的子类型,与列表不是的相同方式List<Object>
的子类型。您可能需要阅读此内容。
但是在Kotlin中,可以使用类型差异来实现。
fun TestGenerics() {
var catMovement1: Movement<Cat> = CatMovementImpl()
var catMovement2: Movement<out Animal> = CatMovementImpl() // works
}
您基本上告诉编译器“接受Movement<Animal>
的所有实现或Movement<S>
以S
为上限的实现Animal
”。
但是,随后出现了问题。您不能调用
val cat: Cat = /* ... */
catMovement2.moveAnimal(cat) // error
为您提供错误
投影类型为
Movement<out Animal>
的项目禁止使用[...]。
因为T
只能用作生产者(外部头寸),而不能用作消费者(内部头寸),就像这样(用于说明要点的功能):
val c: Cat = catMovement2.getAnimal() // works
当您在out
声明中使用Movement
时,此问题立即变得清楚:
interface Movement<out T : Animal> {
fun moveAnimal(type: T) // error
}
这取决于您的用例,但也许您应该让Kotlin推断类型,即CatMovementImpl
。
var catMovement = CatMovementImpl()
信用额为EpicPandaForce的原因是已经建议在评论中使用out
。