Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Kotlin Inheritance – Overriding properties

So I started learning Kotlin today and got to Classes when I noticed something weird.
When I run this code:

fun main() {
    val dog_1 = Dog("Walrek", 7)
}

open class Animal(
    open val type: String,
    open val name: String,
    open val speed: Int,
) {
    init {
        println("(Ani init) New animal: $type called $name with $speed speed")
    }
}

class Dog(
    override val name: String,
    override val speed: Int,
): Animal("Dog", name, speed) {}

The init method will print out: (Ani init) New animal: Dog called null with 0 speed.

At first I thought I messed up somewhere and somehow I’m not passing the arguments properly into the Animal class, but then I added these two lines of code:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

init {
    println("(Dog init) New animal: $type called $name with $speed speed")
}

into Dog class, and

println(dog_1.name)

in the main function, and got this as an output:

(Ani init) New animal: Dog called null with 0 speed
(Dog init) New animal: Dog called Walrek with 7 speed
Walrek

So now my question is, why weren’t the parameters passed into the Animal class, and yet I can access them as usual after creating the Dog instance?

>Solution :

You should be getting a compiler warning. You should never use open properties or functions at construction time (in init blocks or property declarations), because it causes this kind of unwanted behavior. It’s just about the only way you can get a NullPointerException in Kotlin without using !!.

The reason it happens is that the superclass’s constructor (which includes init blocks and property declarations) is run before the subclass. Since you override the property name in the subclass, the backing field of the property name has not yet been initialized by the time init of the superclass is called, so the property returns the default Java field value of null. In the case of speed, the field type is a Java primitive int so its default value is 0.

Note that in your specific example, there was no need to override these properties because you are passing these values to the superconstructor anyway. You could remove the open keyword before the properties and declare your Dog like:

class Dog(
    name: String,
    speed: Int,
): Animal("Dog", name, speed) {}

Then it will behave properly.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading