Thomas Cook
Thomas Cook

Reputation: 4863

Override a function type in sub type Kotlin/Java

I have this interface:

// 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>>
}

The implementation is irrelevant to my question in this case. The question is can I override the function types in a sub type. Below is an example, that doesn't compile; hence my reason for asking this question.

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
}

Hopefully the admittedly not compiling code above makes clear my intent. Is this possible with Java/Kotlin? If so, how would I go about it?

Upvotes: 0

Views: 135

Answers (2)

Max Farsikov
Max Farsikov

Reputation: 2763

Probably you need not override but overload.

If yes, just remove keyword override from the derived interface.

If you need override (you are going to use polymorphism) both functions must have the same signature.

It is impossible to override the function:

(Long, Long) -> SimulationState

with function:

(Long, Long, Collection) -> Unit

Upvotes: 0

noktigula
noktigula

Reputation: 445

JVM object structure has an inner pointer to a table of methods available. When you call the method of the object, JVM access this table (let's call it vtable) and, if method is found, it executes it. But what to do if method is not found there? Then it tries to find this method in parent class. These accesses may be detected during compilation, which helps to avoid really complex problems with debugging on runtime.

Now, lets imagine that your example is possible. You have a class which implements ShipState and, through it, it also implements SimulationState. You implement your method integrate from interface ShipState (the one with 3 parameters).

But wait, your object is still of type SimulationState, right? Now let's imagine that you want to create a collection of simulations and process them in single way:

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) }

What happens next? On first iteration, everything is fine. When you call integrate on simpleSimulation JVM access it's vtable, finds implementation of integrate with two parameters and calls it. Fine.

On second iteration, JVM access vtable of object shipSimulation. It tries to resolve method integrate with two parameters and doesn't find it. Okay, what to do next? There are similar method which has three parameters, should we call it? If yes, which parameter do we need to pass? null? Why? What to do in case if your similar method has 5 parameters more? Compiler and runtime are not able to resolve this issues, that's why it's failing.

In terms of Java/Kotlin OOP, what you want to do is not an override. You just adding new method to a new interface, which, by coincidence, looks pretty similar to the other one. However this coincidence doesn't mean that it's same method.

Please take a look on this wonderful article, which explains topic in low-level details.

Upvotes: 2

Related Questions