Home > Blockchain >  Kotlin/Java: Override Abstract Value in Subclass Constructor
Kotlin/Java: Override Abstract Value in Subclass Constructor

Time:11-02

Given an abstract class:

abstract class BobaTea {
    abstract val sweetness: Int
}

I have a subclass in which I want to override sweetness, however I want to do that in the constructor because the value of sweetness cannot be defined at compile-time, I will only know it at run-time. However, my constructor will ensure that all instances of the subclass do indeed implement the abstract value sweetness.

class MatchaBobaLatte : BobaTea() {
    constructor(sweetness: Int) : this() {
        this.sweetness = sweetness  // This fails with "val cannot be reassigned"
    }
}

Why doesn't this work? I am not reassigning sweetness, I am simply overriding it because it is abstract in the superclass.

Thanks.

CodePudding user response:

overriding an abstract property requires that you override it at the top level and mention override val somewhere.

It can happen either in the primary constructor, e.g.

class MatchaBobaLatte(override val sweetness: Int) : BobaTea() {
    // ...
}

or by explicitly declaring the override val like

class MatchaBobaLatte : BobaTea {
    override val sweetness: Int

    constructor(sweetness: Int) : super() { // Not this()!
        this.sweetness = sweetness
    }
}

or like

class MatchaBobaLatte(sweetness: Int) : BobaTea() {
    // primary constructor parameters are available for instance
    // initializer code
    override val sweetness = sweetness * 2
}

The error you see is result of a combination of multiple things. You try to delegate to a primary this() constructor which doesn't exist but it would be the one that needs to set all val values. The error also appears if you would do

class Reassign {
    val sweetness: Int; // when no value here, then

    // primary ctor must init all vals or you get
    // "Property must be initialized or be abstract"
    constructor() {
        sweetness = 42;
    }

    // can't touch vals in here any more because it runs
    // after "this()"
    constructor(foo: Int) : this() {
        sweetness = foo; // Val cannot be reassigned
    }
}
  • Related