我有
trait Invoker {
val method: Method
}
Intellij IDEA代码检查警告我“特征中使用的抽象值”。一切都很好。在特质中使用抽象值有什么问题吗?如果是这样,我应该如何指定特征的所有扩展器必须定义方法属性?
答案 0 :(得分:38)
这意味着以下奇怪之处:</ p>
trait A {
val i: String
def j: String
}
class C extends A {
println ("val i = " + i)
println ("def j = " + j)
val i = "i"
def j = "j"
}
val c = new C
// prints
// val i = null
// def j = j
因此,您可以看到i
在null
中被构造函数最终覆盖之前,已初始化为默认值(AnyRef
的{{1}})。 (C
声明会立即重新引用。)
为了避免这种情况,如果可能的话,必须将def
初始化放在构造函数的开头。
以下情况中的其他奇怪(以及如何解决)
考虑
val
现在我们似乎运气不好;在我们的超类trait A {
val i: String
def j: String
}
abstract class D extends A {
println ("val i = " + i)
println ("def j = " + j)
}
class C extends D {
val i = "i"
def j = "j"
}
val c = new C
// prints
// val i = null
// def j = null
尝试打印它们之前,我们似乎没有机会初始化val i
和 def j
。
为了解决这个问题,我们必须使用早期定义(§5.1.6Scala reference):
D
它有效!
答案 1 :(得分:6)
在特征中使用抽象val有很多充分的理由。不幸的是,IntelliJ IDEA并没有区分它们,只是简单地警告它们不受普遍使用。实际上,这意味着忽略了IntelliJ IDEA警告。