Unexpected result when overriding 'val'

In Scala 2.10.4, Given the following class:

scala> class Foo { | val x = true | val f = if (x) 100 else 200 | } defined class Foo 

The following two examples make sense to me:

 scala> new Foo {}.f res0: Int = 100 scala> new Foo { override val x = false}.f res1: Int = 200 

But why does this call not return 100 ?

 scala> new Foo { override val x = true }.f res2: Int = 200 
+6
source share
1 answer

Since vals are not initialized more than once, x is actually null (or false for the default Boolean ) during initialization of Foo , and then initialized in an anonymous class that extends Foo in your example.

We can test it easier with 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 

There is a full explanation in the Scala FAQ . Excerpts:

Naturally, when val is redefined, it is not initialized more than once. Thus, although x2 in the above example seems to be defined at every point, it is not: an overridden val will appear to be zero when constructing superclasses, just like the abstract value val.

An easy way to avoid this would be to use a lazy val or def if the reference to Val can be overridden.

Alternatively, you can use the -Xcheckinit flag for the compiler to warn you of potential initialization errors like this.

+11
source

Source: https://habr.com/ru/post/984331/


All Articles