Perché vals non vengono inizializzati più di una volta, è in realtà x
null
(o false
per un default Boolean
) durante l'inizializzazione di Foo
, e poi inizializzata nella classe anonima che sta estendendo Foo
nel tuo esempio.
Siamo in grado di testare più facilmente con un AnyRef
:
class Foo {
val x = ""
val f = if (x == null) "x is null" else "not null"
}
scala> new Foo { override val x = "a" }.f
res10: String = x is null
scala> new Foo {}.f
res11: String = not null
C'è una spiegazione completa nel Scala FAQ. Estratto:
Naturalmente quando una val è ignorata, non viene inizializzata più di una volta. Quindi, anche se x2 nell'esempio precedente è apparentemente definita in ogni punto, questo non è il caso: una val override sembrerà essere nullo durante la costruzione di superclassi, così come una val astratta.
Un modo semplice per evitare ciò sarebbe utilizzare un valore lazy val o def, se la valzione a cui si fa riferimento può essere sovrascritta.
Inoltre, è possibile utilizzare il flag -Xcheckinit
compilatore mettere in guardia su possibili errori di inizializzazione come questo.
fonte
2015-03-27 17:53:47
Dude, http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html –