如果我写的:
trait T {
val t = 3
val u = 1::t::Nil
}
class U extends T {
override val t = 2
}
(new U).u
它显示了这一点。
List(1, 0)
我应该如何改变上面的代码,使其显示如下:
List(1, 2)
即override val t
设置的值t
的u
的特质T
?
如果我写的:
trait T {
val t = 3
val u = 1::t::Nil
}
class U extends T {
override val t = 2
}
(new U).u
它显示了这一点。
List(1, 0)
我应该如何改变上面的代码,使其显示如下:
List(1, 2)
即override val t
设置的值t
的u
的特质T
?
要做到这一点的方法之一是延缓评估u
用def
或lazy val
如下:
trait T {
def t = 3
def u = 1::t::Nil
}
class U extends T {
override def t = 2
}
(new U).u
要么
trait T {
val t = 3
lazy val u = 1::t::Nil
}
class U extends T {
override val t = 2
}
(new U).u
它们的区别如下:
val
使初始化期间的表达评估 def
使得每次的表达评估u
用于 lazy val
使得它在第一次评估u
的使用和缓存结果 尝试使用早期的初始化:
scala> trait T {
| val t = 3
| val u = 1::t::Nil
| }
defined trait T
scala> class U extends {
| override val t = 2;
| } with T
defined class U
scala> (new U).u
res1: List[Int] = List(1, 2)
例如参见这里关于早期初始化的更多信息。
所有斯卡拉声明风格只是一种假象。 Scala是建立在JVM和工作像Java。
Evetything是一类和应该独立于它的使用(Java是不C ++和支持增量生成与其利弊)。 各性状都有自己的初始化代码和多性状类运行相应的初始化代码逐个。 如果您使用的是只有在子类中比它的价值将为空初始化过程中设置一些声明AnyRef。
我守护自己与specifing约定规则:每VAL应该是最终或懒惰( 为什么在非final类使用普通VAL )。 所以,我不关心初始化顺序,并且还可以假装我使用的声明性语言。
另外我使用的选项-Xcheckinit
:运行时检查添加到现场存取。