Reputation: 8768
Can someone help me understand the following behavior?
Simply put: what is the difference between the following two cases where...
c
+ trait t
scala> class c {val x=true; val y=this.x}
defined class c
scala> trait t {}
defined trait t
scala> new c with t
res32: c with t = $anon$1@604f1a67
scala> new {val x=true; val y=this.x} with t
<console>:9: error: type mismatch;
found : type
required: ?{def x: ?}
<console>:9: error: value x is not a member of object $iw
new {val x=true; val y=this.x} with t
What's the difference between these two cases?
Thanks!
Upvotes: 24
Views: 20927
Reputation: 51109
You've stumbled on "early definition" syntax (more info).
Check out section 5.1.6 of the language specification:
An early definition is type-checked and evaluated in the scope which is in effect just before the template being defined, augmented by any type parameters of the enclosing class and by any early definitions preceding the one being defined. In particular, any reference to
this
in the right-hand side of an early definition refers to the identity ofthis
just outside the template. Consequently, it is impossible that an early definition refers to the object being constructed by the template, or refers to one of its fields and methods, except for any other preceding early definition in the same section.
In your case the problem is with this.x
. If you replace it with just x
, so you're referring to the "preceding early definition" as mentioned in the last sentence above (thanks, @som-snytt !), it compiles.
Of course, you probably didn't intend to write an early initializer, so just write it as per Kristian Domagala's answer.
Upvotes: 5
Reputation: 3696
Is this what you're after:
new t {val x=true; val y=this.x}
If you have another trait, u {}
, you can write new t with u {val x=true; val y=this.x}
Upvotes: 29