0

In my understanding,

When an object of subclass is created, the constructor of the subclass first calls the constructor of parent class. In the parent constructor, if there is a def that has been overridden then the overridden copy is called.

Due to all this, in the following code the 'env' variable is not set to (intuitively) the correct length of 1.

class C {
  val range: Int = 10
  val env = new Array[Int](range)
}


class A extends C {
  override val range = 1
}

val a = new A 
a.env.length //0 instead of 1 or 10

Now, if we define range as a lazy val then the problem goes away and a.env.length yields 1. I am not able to understand why? (because the moment new Array[Int](range) is called, I suppose, it will call the getter for range from subclass and that will return 0.

Can someone clarify, why lazy val solves this issue.

Dev Maha
  • 1,133
  • 1
  • 11
  • 24

1 Answers1

1

The one-question FAQ moved to:

http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html

lazy val is on-demand initialization, whereas an "eager" val, a misnomer, waits patiently, even with indifference, for the constructor in which it is defined to be run.

som-snytt
  • 39,429
  • 2
  • 47
  • 129
  • This FAQ gives solution to the problem but not the reasoning. The question I have is -> When a val is declared as lazy, its initialization is deferred until it is accessed for the first time. In the given case `range` is accessed for the first time in `val env = new Array[Int](range)`, at this time `range` is uninitialized, so how is `env` still of right length. Note that `env` is not a lazy val – Dev Maha Dec 27 '13 at 07:16
  • Think of lazy as a def with value cached, not as deferred. That's what I meant by on-demand. The definition of env just invokes the accessor of range. In the lazy case, it's computed right away. In the regular case, it sees the uninitialized value of the field. – som-snytt Dec 27 '13 at 07:41
  • som-syntt thanks for replying. Is there somewhere where I can get more details on this, for every site/book I referred simply say that 'lazy val' is initialized when it is first accessed. In here, `env` accesses `lazy val range` but the sub class getter I believe should still return 0. – Dev Maha Dec 28 '13 at 23:52
  • Not sure why you believe that. See http://stackoverflow.com/a/17642466/1296806 where you see what the accessor does. It's nothing special that it is called from the super class ctor. – som-snytt Dec 29 '13 at 00:40