我有这个界面:
// Interface for any simulation that is integrated against dt
interface SimulationState {
fun integrate(totalTime: Long, deltaTime: Long) : SimulationState
fun interpolate(alpha: Double, previousState: SimulationState) : SimulationState
fun preRender() : Collection<Pair<Int, Int>>
}
在这种情况下,实现与我的问题无关。问题是我可以覆盖子类型中的函数类型吗?下面是一个示例,该示例未编译;因此,我提出这个问题的原因。
interface ShipState : SimulationState {
// Still in abstract, just hope I can somehow override the function type...
override fun integrate(totalTime: Long,
deltaTime: Long,
asteroidVectors: Collection<Pair<Double, Double>>) : SimulationState
}
希望上面公认的未编译代码清楚地表明了我的意图。 Java / Kotlin是否可能?如果是这样,我将如何处理?
答案 0 :(得分:2)
JVM对象结构具有指向可用方法表的内部指针。当您调用对象的方法时,JVM访问该表(将其称为vtable),如果找到了方法,它将执行该表。但是,如果那里找不到方法怎么办?然后,它尝试在父类中找到此方法。可以在编译期间检测到这些访问,这有助于避免在运行时调试时出现非常复杂的问题。
现在,让我们想象您的例子是可能的。您有一个实现ShipState
的类,并通过它实现了SimulationState
。您可以从接口integrate
(带有3个参数的接口)实现方法ShipState
。
但是,等等,您的对象仍然是SimulationState
类型,对吗?现在,让我们假设您想创建一组仿真并以单一方式处理它们:
val simpleSimulation = SimulationStateImpl() //imaginary implementation of base interface
val shipSimulation = ShipSimulationImpl() // again imaginary implementation
val simulations = listOf<SimulationState>(simpleSimulation, shipSimulation)
simulations.forEach { it.integrate(totalTime = 100, deltaTime = 50) }
接下来会发生什么?在第一次迭代中,一切都很好。当您在integrate
上调用simpleSimulation
进行JVM访问时,它是vtable,它用两个参数查找integrate
的实现并调用它。很好
在第二次迭代中,对象shipSimulation
的JVM访问vtable。它尝试使用两个参数解析方法integrate
,但找不到它。好吧,下一步该怎么做?有类似的方法具有三个参数,我们应该调用它吗?如果是,我们需要传递哪个参数? null
?为什么?如果您的类似方法多了5个参数,该怎么办?编译器和运行时无法解决此问题,这就是失败的原因。
就Java / Kotlin OOP而言,您要做的不是override
。您只需将新方法添加到新接口,巧合的是,该接口看起来与另一个接口非常相似。但是,这种巧合并不意味着它是相同的方法。
请查看this wonderful article,该主题以较低级别的细节进行了解释。
答案 1 :(得分:0)
可能您不需要override
,而overload
。
如果是,只需从派生界面中删除关键字override
。
如果您需要override
(将使用多态性),则两个函数必须具有相同的签名。
无法覆盖该功能:
(Long, Long) -> SimulationState
具有功能:
(Long, Long, Collection) -> Unit