This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Unexpected behavior with traits ...

2 replies
Lg
Joined: 2011-03-09,
User offline. Last seen 42 years 45 weeks ago.

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

Johannes Rudolph 2
Joined: 2010-02-12,
User offline. Last seen 42 years 45 weeks ago.
Re: Unexpected behavior with traits ...

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

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
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.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland