Problem of initialization


#1

I just made a simple code of my game, but had a problem:

class Player(x: Float, y: Float) : GameObject(x, y) {
    override val width = 3F
    override val height = 4F
    override val initState = State.down
}

abstract class GameObject(x: Float, y: Float) {
    abstract val width: Float
    abstract val height: Float
    abstract val initState: State

    val bounds = Bounds(x, y, width, height)
    var state: State = initState
}

data class Bounds(var x: Float, var y: Float, val width: Float, val height: Float)
enum class State {up, down, stop }

fun main(args: Array<String>) {
    val player = Player(1F,2F)
    println(player.bounds)
    println(player.state)
}

I expected to get bounds with width of 3F, height of 4F and player start with down state.

But I actually got:

Bounds(x=1.0, y=2.0, width=0.0, height=0.0)
null

Which means you can assign a null value to a none null property without even a warning!

In addition :slight_smile:

abstract class NotNull<T> {
    val notNull: T = initValue
    protected abstract val initValue: T
}

class StringNotNull : NotNull<String>() {
    override val initValue = "not null"
}

fun main(args: Array<String>) {
    val snn=StringNotNull()
    val notNull:String=snn.notNull
    if(notNull==null){
        println("Impossible")
    }else{
        println("Surely not null")
    }
}

I got a “Impossible” here !

Is it a bug? How can I fix it?


#2

This is not a bug. You’re accessing a property from the base class constructor before the derived class constructor which initializes the property has had a chance to execute. This problem exists in Java as well.

Future versions of Kotlin will have an inspection that will report such problems as warnings.


#3

I found a way to solve it.

class Player(x: Float, y: Float) : GameObject(x, y) {
    override val width: Float get() = 3F
    override val height: Float get() = 4F
    override val initState: Float get() = State.down
}

A little verbose.
Thank you all the same!