1

I have a problem understanding how class parameter value behaves between abstract/concrete classes.

Abstract class example:

abstract class A {

   init {
       initStuff()
   }

   fun initStuff() {
       additionalInit()
   }

   abstract fun additionalInit()
}

Concrete class example:

class B(val exParam: Int): A {

    init {
       println("$exParam") // This would give expected value.
    }

    override fun additionalInit() {
       println("$exParam") // Always zero even if exParam value is set.
    }
}

My question is that based on my understanding, I want to call B(1000) and expect both println inside the B class to print 1000 but this was not the case so my understanding is clearly off here so anyone can light me to the right understanding?

Rhama Arya Wibawa
  • 250
  • 1
  • 2
  • 15

2 Answers2

5

Note what you are using here is an anti-pattern, i.e. calling a method from the constructor which is overridable by subclasses and that for the very reason you now realise as an unexpected behaviour.

Now what's happening here: before you can even initialize B A needs to be constructed first. So the constructors and init of A get called first. But the variable for B is not assigned yet at that very moment. So that's why we still have that 0 there. Even if you set a default value of, lets say -1 (i.e. val exParam : Int = -1), you will see rather 0 here as output.

Summarizing: never ever call overridable functions in a constructor or init... Read more about it here: What's wrong with overridable method calls in constructors?

Roland
  • 22,259
  • 4
  • 57
  • 84
2

inheritance here works just like in Java. If you were to translate your construct into Java code, it would look something like this:

abstract class A {

    public A() {
        additionalInit();
    }

    abstract void additionalInit();

}

class B extends A {

    private int exParam;

    public B(int exParam) {
        // You can see here that this.exParam is initialized AFTER you're calling the super constructor
        super();
        this.exParam = exParam;
    }

    // getters and setters

}

Your IDE should give you a warning if you are trying to call abstract function from the init block because of this.

Dominik G.
  • 610
  • 3
  • 7