Scala: выполняется переопределение родительского кода значения, но значение не назначено в родительском коде - PullRequest
0 голосов
/ 05 июня 2018

Выполнение приведенного ниже кода:

class Parent {
  val value = {
    println("Setting value in parent")
    "ParentVal"
  }
  println(s"Parent value is ${value}")
}

class Child extends Parent {
  override val value = {
    println("Setting value in child")
    "ChildVal"
  }
  println(s"Child value is ${value}")
}

new Child

Создает этот вывод:

Setting value in parent
Parent value is null
Setting value in child
Child value is ChildVal

Таким образом, выполняется код, связанный с назначением родительского значения, однако значение на самом деле не назначается вродитель.После этого запускается дочерний код, который присваивает значение, как и ожидалось.

Может ли кто-нибудь объяснить цепочку событий здесь на более низком уровне?

1 Ответ

0 голосов
/ 05 июня 2018

Вы можете думать о val, как если бы это была комбинация закрытой переменной-члена без методов установки + метода получения.Если вы переписываете свой код без val s, это будет выглядеть примерно так:

class Parent {
  private[this] var parentValue = {
    println("Setting value in parent")
    "ParentVal"
  }
  def value: String = parentValue
  println(s"Parent value is ${value}")
}

class Child extends Parent {
  private[this] var childValue = {
    println("Setting value in child")
    "ChildVal"
  }
  override def value = childValue
  println(s"Child value is ${value}")
}

new Child

Как и в оригинале, он печатает:

Setting value in parent
Parent value is null
Setting value in child
Child value is ChildVal

Это потому, что родительский конструкторвызывает метод value, но этот метод переопределяется на def value = childValue.Возвращаемое значение childValue равно null, поскольку при вызове родительского конструктора дочерний конструктор еще не вызывался.

Подробнее о порядке инициализации объекта можно прочитать здесь .


Связанные ответы:

  1. Почему реализация абстрактного метода с использованием val и вызов из суперкласса в выражении val возвращает NullPointerException .

  2. Утверждение с require в абстрактном суперклассе создает NPE

...