[英]Kotlin class parameter value between abstract class and its concrete class
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? 我的问题是,根据我的理解,我想调用
B(1000)
并期望B类中的两个println
都可以打印1000
但事实并非如此,因此我的理解很明显,因此任何人都可以将我理解为正确的理解?
Note what you are using here is an anti-pattern, ie 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. 现在,这里发生了什么:在甚至可以初始化
B
之前,首先需要构造A
So the constructors and init
of A
get called first. 因此,首先调用
A
的构造函数和init
。 But the variable for B
is not assigned yet at that very moment. 但是那时
B
的变量尚未分配。 So that's why we still have that 0
there. 这就是为什么我们那里仍然有
0
。 Even if you set a default value of, lets say -1
(ie val exParam : Int = -1
), you will see rather 0
here as output. 即使您将默认值设置为
-1
(即val exParam : Int = -1
),您在此处也会看到0
。
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? 总结:永远不要在构造函数或init中调用可重写函数...在此了解更多信息:构造函数中的可重写方法调用有什么问题?
inheritance here works just like in Java. 这里的继承就像在Java中一样工作。 If you were to translate your construct into Java code, it would look something like this:
如果要将构造转换为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
}
Your IDE should give you a warning if you are trying to call abstract function from the init block because of this. 因此,如果您试图从init块调用抽象函数,您的IDE应该给您警告。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.