Kotlin: Accessing non final property name in constructor

Viewed 794

This question has been answered in Stack overflow before but since I am new to Kotlin I didn't understand that. It would be very helpful If someone can tell me what is wrong in the below code (In simple language) and how I can fix that. I am getting a warning from IntelliJ IDEA under 'name' property in Country class that I am trying to access non final property name in constructor. What is wrong with that?

open class Country (n : String? = null)
{
    open var name : String? = n

    init {
        if (n==null)
        {
            this.name = "Unknown Country"
        }
        else
        {
            this.name = n
        }
    }

    fun printCountryName()
    {
        println("Country Name : ${this.name}")
    }

}

class India constructor(n: String? = null, p: Int, g: Double ): Country(n)
{
    override var name : String? = "India"

}
1 Answers

You need to remember that properties aren't just fields. They're fields + getters/setters. By declaring name as open you let your subclasses change the implementation of the setName(). Then, any subclass can do something like this:

class MyCountry : Country("foo") {
    override var name: String?
        get() = null
        set(value) {}
}

This way the constructor of Country won't be able to set the name.

open is for changing the implementation, not for changing a stored value. If you need some default value then just set it as normal:

class India constructor(p: Int, g: Double ): Country("India")

To fix your problem you need to just remove open from name, because from your example it doesn't seem you really need it.

Update

Also, I see potential bugs/mistakes in your code:

  1. If you check Country name for nullability when constructing and replace null with "Unknown Country" then why name proeperty is String? and not String? It seems you don't want to have nulls there, but still allows them.
  2. I guess it doesn't make sense to change the name of existing country, so I believe you could use val instead of var.
Related