我在理解抽象/具体类之间的类参数值表现方式时遇到问题。
抽象类示例:
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
,但事实并非如此,所以我的理解是显然不在这里,所以任何人都可以照亮我对它的正确理解?
答案 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应该给您警告。