- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Unexpected behavior with traits ...
Wed, 2011-06-29, 15:40
Values in a trait defined in terms of abstract fields assume default
values for these fields. An example illustrates:
----------------
scala> trait Pt {
| val x : Int
| val y : Int
| val d = x + y
| def dist = x + y
| }
defined trait Pt
scala> val pt = new Pt{val x = 3; val y = 4}
pt: java.lang.Object with Pt = $anon$1@4cb0f24a
scala> pt.d
res0: Int = 0
scala> pt.dist
res1: Int = 7
-----------------
The natural behavior is for the binding of 'd' to be delayed until all
abstract dependencies are defined.
Best,
Lal
Wed, 2011-06-29, 16:37
#2
Re: Unexpected behavior with traits ...
On Wed, Jun 29, 2011 at 11:40, Lg wrote:
> Values in a trait defined in terms of abstract fields assume default
> values for these fields. An example illustrates:
Wrong. It doesn't assume anything -- the values used are those
assigned to such fields at the time the constructor in question is
called.
> ----------------
> scala> trait Pt {
> | val x : Int
> | val y : Int
> | val d = x + y
> | def dist = x + y
> | }
> defined trait Pt
>
> scala> val pt = new Pt{val x = 3; val y = 4}
> pt: java.lang.Object with Pt = $anon$1@4cb0f24a
>
> scala> pt.d
> res0: Int = 0
>
> scala> pt.dist
> res1: Int = 7
> -----------------
>
> The natural behavior is for the binding of 'd' to be delayed until all
> abstract dependencies are defined.
That isn't natural -- it would be a violation of contructor order.
There's a "lazy" keyword that specifically says it is *not* to follow
the normal order of initialization, and, instead, delay binding until
"d" is called.
Let's see, then, the initialization order (though this is really not
appropriate to scala-language -- please keep such posts to
scala-users).
val pt = new AnyRef with Pt { val x = 3; val y = 4 }
First, call AnyRef's constructor.
Next, call Pt's constructor.
Finally, call the structural type constructor.
If you want to initialize x and y earlier, use the syntax for early
initialization:
val pt = new { val x = 3; val y = 4 } with Pt
See also http://stackoverflow.com/questions/3830332/scala-initialization-behaviour.
Hi Lal,
On Wed, Jun 29, 2011 at 4:40 PM, Lg wrote:
> The natural behavior is for the binding of 'd' to be delayed until all
> abstract dependencies are defined.
Alas, that's not how it's spec'd. In fact, `val d` is initialized
before `x` and `y`. Use `lazy val d` if you want to make this problem
go away in this case. See this stackoverflow question for more
pointers:
http://stackoverflow.com/questions/4701749/nullpointerexception-when-acc...
HTH
Johannes
-----------------------------------------------
Johannes Rudolph
http://virtual-void.net