有没有办法用声明类型的子类型覆盖抽象 属性 ?

Is there a way to override an abstract property with a subtype of the declared type?

考虑下面的例子:我有一个Animal的抽象class,每个动物都有嘴,但是因为每个动物的嘴都不一样,所以嘴class也是抽象的:

abstract class Animal {
    var numberLegs: Int = 4
    var mouth: Mouth? = null
} 

abstract class Mouth {
    abstract fun makeSound()
}

我现在可以创建 Dog 和 DogMouth:

class Dog: Animal() {
    override var mouth: Mouth = DogMouth()
}

class DogMouth: Mouth() {
    override fun makeSound() {
        println("Bark!")
    }
}

但这让我也可以为狗分配其他类型的嘴巴,这是我不想要的,例如:

class CatMouth: Mouth() {
    override fun makeSound() {
        println("Meow!")
    }
}

fun main() {
    val dog = Dog()
    dog.mouth.makeSound()   // will print "Bark!"
    dog.mouth = CatMouth()  // I don't want this to work
    dog.mouth.makeSound()   // will print "Meow!"
}

设置override var mouth: DogMouth = DogMouth()无效。

如何确保狗只有 DogMouths(和其他狗 body 部分)?

解决了类似的问题 here and here。 解决方案是使用通用参数:

abstract class Animal<MouthType: Mouth> {
    var numberLegs: Int = 4
    abstract var mouth: MouthType
} 

class Dog: Animal<DogMouth>() {
    override var mouth: DogMouth = DogMouth()
}

这使得 dog.mouth = CatMouth() 因类型不匹配而失败。

需要添加更多 body 部分额外的泛型:

abstract class Animal<MouthType: Mouth, EarType: Ear, TailType: Tail> {
    var numberLegs: Int = 4
    abstract var mouth: MouthType
    abstract var ear: EarType
    abstract var tail: TailType
}