Scala 2.8: как инициализировать дочерний класс - PullRequest
2 голосов
/ 22 апреля 2011

Рассмотрим следующий код:

abstract class X {
  def a:Unit
  a
}

class Y extends X {
  var s:String = "Hello"
  def a:Unit = println ("String is "+s)
}

Это дает следующий вывод:

scala> new Y
String is null
res6: Y = Y@18aeabe

Как мне заставить родительский класс X ждать, пока s будетинициализируется при вызове a

1 Ответ

6 голосов
/ 22 апреля 2011

Родительские поля и родительский конструктор всегда инициализируются и запускаются перед дочерним полем и конструктором.Это означает, что вызов a происходит до того, как ваш var s установлен в дочернем классе.

В общем, плохая идея вызывать виртуальный метод из конструктора;C ++ даже запрещает его (или, вместо того, чтобы запрещать его, не вызывает метод, реализованный в дочернем классе при вызове из конструктора суперкласса).

Однако вы можете это исправить, если включите var sвместо class Y в lazy val или def.lazy val s инициализируются при первом обращении к их значению, независимо от того, кем;def s не создает проблем с инициализацией, таких как var s или val s.Однако будьте осторожны, чтобы не вызывать любую другую неинициализированную структуру из реализации a, так как та же проблема появится снова.

Редактировать:

Вытакже можно использовать функцию «ранних определений» (или ранней инициализации) в Scala:

class Y extends {
  var s = "Hello"
} with X {
  def a: Unit = println ("String is "+s)
}
...