Kotlin 如何使用超类型参数重写方法

Kotlin 如何使用超类型参数重写方法,kotlin,inheritance,overriding,Kotlin,Inheritance,Overriding,我有一个像这样的水果课程 open class Fruit(var taste: String) { open fun consume(from: Fruit) { taste = from.taste } } class Apple( var color: String, taste: String ): Fruit(taste) { // caution: method overrides nothing override

我有一个像这样的
水果
课程

open class Fruit(var taste: String) {

    open fun consume(from: Fruit) {
        taste = from.taste
    }
}
class Apple(
    var color: String,
    taste: String
): Fruit(taste) {

    // caution: method overrides nothing
    override fun consume(from: Apple) {
        super.consume(from)
        color = from.color
    }
}
我有一个
Apple
类,它像这样扩展了
Fruit

open class Fruit(var taste: String) {

    open fun consume(from: Fruit) {
        taste = from.taste
    }
}
class Apple(
    var color: String,
    taste: String
): Fruit(taste) {

    // caution: method overrides nothing
    override fun consume(from: Apple) {
        super.consume(from)
        color = from.color
    }
}
这是我的使用代码:

val fruit: Fruit = Apple(color = "green", taste = "sweet")
val badFruit = Apple(
    color = anyOf("red", "blue", "golden"),
    taste = anyOf("sour+", "sweet+", "chilli+")
)

fruit.consume(from = badFruit)

println("BadFruit: $badFruit")
println("InfectedFruit: $fruit")
问题: 我无法在
Apple
类中重写以下方法:

override fun consume(from: Apple) {
    super.consume(from)
    color = from.color
}
为了正确重写这个方法,我需要传入一个Fruit类的实例(就像超级方法一样)。如果我这样做,我将始终必须检查
Fruit
实例是否实际上是
Apple
实例。但是,它不应该只与前者一起工作,因为苹果扩展了水果吗

我如何实现这样的功能,当我在
水果:水果=苹果(…)
上调用
消费()
时,它实际上调用了
苹果消费()
方法


做这件事的好方法是什么?

虽然在评论中提出了技术替代方案,但我想补充另一个观点。我们在这里看到的是一个类设计问题,当试图将继承用于真正的泛化/专门化关系之外的任何事物时,会出现这个问题

该示例声明:

  • 每个
    水果
    必须能够
    消费另一个
    水果
  • 苹果是一种水果
  • 那么这个想法是:


    • 苹果
      不得
      食用任何种类的
      水果
      ,只能食用
      苹果
      虽然在评论中提出了技术替代方案,但我想补充另一个观点。我们在这里看到的是一个类设计问题,当试图将继承用于真正的泛化/专门化关系之外的任何事物时,会出现这个问题

      该示例声明:

    • 每个
      水果
      必须能够
      消费另一个
      水果
    • 苹果是一种水果
    • 那么这个想法是:


      • 苹果
        不得
        食用任何种类的
        水果
        ,只能食用
        苹果
        。这似乎是XY问题的一个例子,在这里合成可以代替“静态固有”。你可能想看看我对一个类似问题的回答。另外,请提供有关您试图解决的实际问题的更多信息。如果您希望Apple类仅使用Apple,则只需将Fruit类设置为泛型逆变参数。或者,如果想要同时接受这两个属性,那么只需接受Fruit并执行if检查,如果实例是Apple,如果是,则更改color属性。@AnimeshSahu我想避免使用泛型。但是,这似乎是公平的,这将需要“生产者输入,消费者输出”之类的实现。这似乎是XY问题的一个例子,在这里,合成可以有帮助,而不是“静态固有”。你可能想看看我对一个类似问题的回答。另外,请提供有关您试图解决的实际问题的更多信息。如果您希望Apple类仅使用Apple,则只需将Fruit类设置为泛型逆变参数。或者,如果想要同时接受这两个属性,那么只需接受Fruit并执行if检查,如果实例是Apple,如果是,则更改color属性。@AnimeshSahu我想避免使用泛型。但是,这似乎是公平的,这将需要“生产者进来,消费者出去”之类的实现。例如,假设我有一个果核。它包含大小和重量等基本属性。我创建了CoreFruit的两个子类;叫做酸果和甜果。现在,如果SourFruit在CoreFruit类型的
        列表中,我打算手动创建底层SourFruit的副本,比如
        sourFruitButTypedAsFruit.copy()
        ;我如何确保这将复制SourFruit和CoreFruit的属性
        consume()
        类似,但它将一个水果写入另一个水果。你能举个例子吗?请看上面答案中添加的通过引用基类复制派生类一节。我同意你的继承建议。例如,假设我有一个果核。它包含大小和重量等基本属性。我创建了CoreFruit的两个子类;叫做酸果和甜果。现在,如果SourFruit在CoreFruit类型的
        列表中,我打算手动创建底层SourFruit的副本,比如
        sourFruitButTypedAsFruit.copy()
        ;我如何确保这将复制SourFruit和CoreFruit的属性
        consume()
        类似,但它将一个水果写入另一个水果。你能举个例子吗?请看上面答案中增加的通过引用基类复制派生类一节。