I was working with scala and did something like this:
trait Foo { val a: String }
trait Foo2 extends Foo { val a = "foo" }
trait Bar extends Foo { val b = a + "-bar" }
object Bar2 extends Bar with Foo2
I expected that Bar2.b would be "foo-bar", but it ends up being "null-bar". Bar2.a is "foo" as expected.
If I change from val to def for definitions of 'a' like this:
trait Foo { def a: String }
trait Foo2 extends Foo { val a = "foo" }
trait Bar extends Foo { val b = a + "-bar" }
object Bar2 extends Bar with Foo2
Bar2.b is actually "foo-bar".
In example 2, the def 'a' from Foo2 that implements the abstract one in Foo is put into the definition of Bar2 before the val 'b' is evaluated. In example 1, the val 'a' from Foo2 overrides the val 'a' from Foo after val 'b' is defined in Bar/Bar2.
Why is this the case? Why do val and def implement abstract methods at different times?