Значение параметра класса Котлина между абстрактным классом и его конкретным классом - PullRequest
0 голосов
/ 29 августа 2018

У меня проблема с пониманием того, как значение параметра класса ведет себя между абстрактными / конкретными классами.

Пример абстрактного класса:

abstract class A {

   init {
       initStuff()
   }

   fun initStuff() {
       additionalInit()
   }

   abstract fun additionalInit()
}

Пример конкретного класса:

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.
    }
}

Мой вопрос заключается в том, что, исходя из моего понимания, я хочу позвонить B(1000) и ожидать, что оба значения println внутри класса B выведут 1000, но это был не тот случай, поэтому мое понимание здесь явно не так, чтобы любой мог зажечь меня до правильного понимания?

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

наследование здесь работает так же, как в Java. Если бы вы перевели свою конструкцию в код Java, она бы выглядела примерно так:

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

}

Ваша IDE должна дать вам предупреждение, если вы пытаетесь вызвать абстрактную функцию из блока init из-за этого.

0 голосов
/ 29 августа 2018

Обратите внимание, что вы используете здесь анти-паттерн, то есть вызов метода из конструктора, который можно переопределить подклассами и который по той самой причине, которую вы теперь понимаете как непредвиденное поведение.

Теперь, что здесь происходит: прежде чем вы сможете даже инициализировать, необходимо сначала создать B A. Таким образом, сначала вызываются конструкторы и init из A. Но переменная для B еще не назначена в тот самый момент. Вот почему у нас все еще есть это 0. Даже если вы установите значение по умолчанию, скажем, -1 (т.е. val exParam : Int = -1), вы скорее увидите здесь 0 в качестве вывода.

Подводя итог: никогда не вызывайте переопределяемые функции в конструкторе или init ... Подробнее об этом здесь: Что не так с вызовами переопределяемых методов в конструкторах?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...