Union types

Here’s another use-case. I have class that implements an abstract game element:

abstract class Element {
    var posX = 0.0f
    var posY = 0.0f
    var posZ = 0.0f
    fun move(x: Float, y: Float, z: Float) { /* ... */ }
    protected fun doSomething() { /* ... */ }
    // and much more
}

The Element is part of a module that’s the game’s engine. The game has an element for the player, which is part of the concrete game implementation, not part of the engine, i.e. it’s in a different module.

class PlayerImpl: Element(), IPlayerExtras {
    override var phi = 0.0f
    // ...
}

The engine provides an interface for the player’s extra values.

interface IPlayerExtras {
    val phi: Float
}

But here’s the problem: The engine can’t easily deal with player elements since in Kotlin I cannot declare a variable like val player: Element & IPlayerExtras.

// engine
abstract class App {
    abstract val player: IPlayerExtras
    fun movePlayer() {
        // cannot access player.posX without type assertion, which is inefficient
        if (player is Element) { /* ... */ }
    }
}
// game implementation
class AppImpl: App {
    override val player = PlayerImpl()
}

To solve the problem, I have two choices. Either I introduce a new level in the inheritance chain like this: Element < AbstrPlayer < PlayerImpl. I don’t like this, because I’ve seen too much messy code caused by deeply nested inheritance chains (especially in C++ this seems to be a common problem). I basically want to avoid inheritance chains deeper than one level.

The other solution is what I call the Java way: Make an interface IElement that repeats all the members of Element, then derive an IPlayer from IElement, IPlayerExtras, and then derive PlayerImpl from IPlayer. I consider this poor style because of two reasons: First, having to repeat all the members of Element in IElement is bloated and Kotlin-unlike. Second, having both an Element and an IElement leads to confusion about which one to use, which I’ve also seen in the past with some Java libraries.

In my opinion, a typealias with an intersection type would be the cleanest and least verbose solution.

typealias PlayerElement = Element & IPlayerExtras