In Kotlin, it warns you when calling an abstract function in a constructor, citing the following problematic code:
abstract class Base {
var code = calculate()
abstract fun calculate(): Int
}
class Derived(private val x: Int) : Base() {
override fun calculate(): Int = x
}
fun main(args: Array<String>) {
val i = Derived(42).code // Expected: 42, actual: 0
println(i)
}
And the output makes sense because when calculate
is called, x
hasn't been initialized yet.
This is something I had never considered when writing java, as I have used this pattern without any issues:
class Base {
private int area;
Base(Room room) {
area = extractArea(room);
}
abstract int extractArea(Room room);
}
class Derived_A extends Base {
Derived_A(Room room) {
super(room);
}
@Override
public int extractArea(Room room) {
// Extract area A from room
}
}
class Derived_B extends Base {
Derived_B(Room room) {
super(room);
}
@Override
public int extractArea(Room room) {
// Extract area B from room
}
}
And this has worked fine because the overriden extractArea
functions don't rely on any uninitialized data, but they are unique to each respective derived class
(hence the need to be abstract). This also works in kotlin, but it still gives the warning.
那么,这是java/kotlin中的糟糕做法吗?如果是,我该如何改进?有没有可能在kotlin中实现而不被警告在构造函数中使用非final函数?
A potential solution is to move the line area = extractArea()
to each derived constructor, but this doesn't seem ideal since it's just repeated code that should be part of the super class.