抽象类与其具体类之间的Kotlin类参数值

时间:2018-08-29 10:23:40

标签: kotlin

我在理解抽象/具体类之间的类参数值表现方式时遇到问题。

抽象类示例:

ifelse

具体的类示例:

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类中的两个B(1000)都打印println,但事实并非如此,所以我的理解是显然不在这里,所以任何人都可以照亮我对它的正确理解?

2 个答案:

答案 0 :(得分:3)

请注意,此处使用的是反模式,即从构造函数中调用一个方法,该方法可以被子类覆盖,并且由于这个原因,您现在意识到这是一种意外行为。

现在这里发生了什么:在甚至初始化B A之前,都需要先构建。因此,首先调用init的构造函数和A。但是此时B的变量尚未分配。这就是为什么我们在那里仍然有0的原因。即使您将默认值设置为-1(即val exParam : Int = -1),您也会在此处看到0作为输出。

总结:永远不要在构造函数或init中调用可重写的函数...在这里了解更多信息:What's wrong with overridable method calls in constructors?

答案 1 :(得分:2)

继承在这里就像在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

}

因此,如果您试图从init块调用抽象函数,您的IDE应该给您警告。