Код в шаблоне ("теле") определения класса, вне определений членов, - это то, что входит в конструктор.Конструкторы для родительских классов всегда вызываются, когда вы инициализируете экземпляр дочернего класса (в этом случае вы вызываете конструктор без аргументов, в противном случае синтаксис будет class B extends A(arg1, arg2) { ... }
).Для получения более подробной информации см. Раздел 5.1 в Спецификации языка Scala .
Именно поэтому println("A")
оценивается в первом случае;это определение val
является частью кода конструктора.
Когда вы думаете о том, что происходит во время построения во втором примере, вы никогда не спрашивали значение x
, определенное в A
;теперь, поскольку это lazy val
, он не будет вычислен до того, как это потребуется.
Вы можете думать о lazy val
s как о методах, которые не принимают аргументов и кэшируют свои выходные данные при первом вызове.,Вы не вызывали этот метод здесь, вы просто определили его.