【发布时间】:2018-05-07 20:42:55
【问题描述】:
在 Kotlin 中,它会在构造函数中调用抽象函数时发出警告,并引用以下有问题的代码:
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)
}
并且输出是有意义的,因为当调用 calculate 时,x 还没有被初始化。
这是我在编写 java 时从未考虑过的,因为我使用这种模式没有任何问题:
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
}
}
这很好用,因为重写的 extractArea 函数不依赖任何未初始化的数据,但它们对于每个派生的 class 都是唯一的(因此需要抽象)。这也适用于 kotlin,但它仍然会发出警告。
那么这是在 java/kotlin 中的糟糕做法吗?如果是这样,我该如何改进它?是否可以在 kotlin 中实现而不被警告在构造函数中使用非最终函数?
一个潜在的解决方案是将行 area = extractArea() 移动到每个派生构造函数,但这似乎并不理想,因为它只是重复的代码,应该是超类的一部分。
【问题讨论】:
-
我重新打开了这个问题,因为它询问的是 Kotlin,而不是 Java。虽然 Kotlin 和 Java 在这方面很相似,但 Kotlin 的实例构造并不等同于 Java 中的实例构造(至少它以不同的构造表示)。
-
@hotkey 好的,我认为接受的答案很好地解释了它。无论如何,我的问题可能与 java 更相关。正是 kotlin 中的警告引发了这个问题。
-
@hotkey "java/kotlin 中的这种糟糕做法也是如此" - 似乎他们都在要求。他们的困惑来自 Java 代码的工作(“错误”没有出现),这是因为它实际上并没有复制 Kotlin 代码正在做的事情。标记副本中的答案肯定解释了他获得的警告和结果。