3

I am trying to overwrite a value in a class. I have the following code:

open class Balloon() {
    open var textSize: Float = 20f
    init {
        Log.i("textSize", textSize.toString())
    }
}
    
class BigBalloon(): Balloon() {
    override var textSize = 30f
}

However, the Log prints out these values:

enter image description here

First Log is from Balloon(), second one is from BigBalloon(). How can it print 0.0 when I overwrote it as 30? Did I implement all of this incorrectly?

deHaar
  • 17,687
  • 10
  • 38
  • 51
Maharkus
  • 2,841
  • 21
  • 35
  • 1
    I just checked your code and it prints `30.0` after creation of a `val bb = BigBalloon()` at `println(bb.textSize)`. The only difference is I had to remove the `init` block because I tried it in the Kotlin Playground which has no LogCat... – deHaar Aug 27 '20 at 13:11
  • So that would mean the value is overridden correctly, but not inside init? – Maharkus Aug 27 '20 at 13:21
  • 1
    don't use non-final properties or functions in init blocks / constructors https://stackoverflow.com/questions/50222139/kotlin-calling-non-final-function-in-constructor-works – IR42 Aug 27 '20 at 13:22

2 Answers2

5

Accessing abstract methods (in this case getTextSize) in constructor is generally discouraged since it might lead to artifacts like yours.

BigBaloon property override actually does two things:

  1. creates new internal field - BigBaloon.textSize
  2. overrides textSize getter and setter to access that field

It's a bit counter intuitive but it does NOT modify value of Baloon.textSize field, it's left untouched and inaccessible since getter/setter no longer use it.

Your issue is when BigBaloons parent Baloon is being initialized it accesses BigBaloon.textSize which is NOT initialized at this point so it returns zero.

Pawel
  • 15,548
  • 3
  • 36
  • 36
3

Kotlin initialization order is not how you understand it, the init block of the Base (Balloon) class is called before the override is done. It is explained better in this answer. And here's the initialization order given in Kotlin docs.

Put the property into primary constructor as:

Balloon(var textSize: Float = 20f) {
    // ...
}

And when you want to change it, just delegate it to the constructor:

class BigBalloon: Balloon(30f)
Animesh Sahu
  • 7,445
  • 2
  • 21
  • 49