Calling base class setters in overridden setter

I have an abstract base class with a property that performs a certain validation. The base class doesn’t allow certain mutations (it could be completely immutable). A derived class, however, does allow to change things that are immutable in the base class. This is achieved by overriding the property with a public setter. But that would by default override the base class setter implementation performing the validation. So I call the setter of the base class in the overriding setter.

abstract class ImmutableBase(name: String) {
    open var name = name
        protected set(name) {
            require(name.isNotEmpty()) { "'name' must not be empty." }
            field = name
        }
}

class MutableDerived(name: String) : ImmutableBase(name) {
    override var name = name
        set(name) {
            super.name = name
        }
}

fun main(vararg args: String) {
	MutableDerived("")
}

Executable example.

However IntelliJ warns me about “Existing backing field is not assigned by the setter” and it doesn’t feel good to me because it is a bit error prone.

setter

Is there a better idea to solve this issue?

Also override the getter so you don’t create an additional backing field in the subclass?

1 Like

This is even more important than you think because in your code you will never change the value of name (https://pl.kotl.in/C5OFnmTzs).

val foo = MutableDerived("foo")
foo.name = "bar"
println(foo.name) // "foo"

foo.name will return the value in the backing field of the derived class while foo.name = "bar" will change the backing field of the super class (which is never read from). So you want your property to be:

public override var name: String
    get() = super.name
    set(name) { super.name = name }

Also you have to add the public modifier when you override the property otherwise it will have the same visibility as the overriden member.

1 Like