How are overridden properties handled in init blocks?

I am trying to understand why the following code produces:

open class Base(open val input: String) {
  lateinit var derived: String

  init {
    derived = input.toUpperCase() // throws!
  }
}

class Sub(override val input: String) : Base(input)

When calling this code:

println(Sub("test").derived)    

it throws an exception because it toUpperCase inputjumps to during the call null. I find this counter intuitive: pass a nonzero value to the first constructor, but does it allow null in the init block of the superclass?

I think I have a vague idea of ​​what can happen: since it inputserves as both an argument to the constructor and a property, the assignment internally calls this.input, but is thisnot completely initialized yet. This is really strange: in the IntelliJ debugger it inputresolves normally (to the value "test"), but as soon as I call the expression evaluation window and inputmanually check , it is unexpectedly null.

Assuming this is the expected behavior, what do you recommend doing, namely, when do you need to initialize fields obtained from properties of the same class?

UPDATE: I published two even more concise code snippets that illustrate where the confusion comes from:

https://gist.github.com/mttkay/9fbb0ddf72f471465afc https://gist.github.com/mttkay/5dc9bde1006b70e1e8ba

+4
2

Java:

class Base {
    private String input;
    private String derived;

    Base(String input) {
        this.input = input;
        this.derived = getInput().toUpperCase();  // Initializes derived by calling an overridden method
    }

    public String getInput() {
        return input;
    }
}

class Derived extends Base {
    private String input;

    public Derived(String input) {
        super(input);    // Calls the superclass constructor, which tries to initialize derived
        this.input = input;  // Initializes the subclass field
    }

    @Override
    public String getInput() {
        return input;   // Returns the value of the subclass field
    }
}

getInput() Sub-, Sub.getInput(). Sub , , Sub.input, - . ; Java-.

, . ( , , , .)

+7

- , input ( JVM). , . input , getInput . getInput , . " ".

-, .

class Sub(input: String) : Base(input) {
    override val input : String
        get() = super.input
}
+3

Source: https://habr.com/ru/post/1623581/


All Articles