Por qué implementa el método abstracto usando val y call desde la superclase en la expresión val return NullPointerException

Tengo una clase abstracta con un método no implementadonumbers que devuelve una lista de números, y este método se utiliza en otra inicialización de la propiedad val:

abstract class Foo {
  val calcNumbers = numbers.map(calc)
  def numbers: List[Double]
}

La clase implementadora implementa utilizando una expresión val:

class MainFoo extends Foo {
  val numbers = List(1,2,3)
}

Esto se compila bien, pero en tiempo de ejecución arroja una NullPointerException y apunta a la línea deval calcNumbers:

[error] (run-main-0) java.lang.ExceptionInInitializerError
[error] java.lang.ExceptionInInitializerError
...
[error] Caused by: java.lang.NullPointerException
...

Sin embargo, cuando cambié el método implementado para def, funciona:

def numbers = List(1,2,3)

¿Porqué es eso? ¿Tiene algo que ver con el orden de inicialización? ¿Cómo se puede evitar esto en el futuro ya que no hay error / advertencia en tiempo de compilación? ¿Cómo permite Scala esta operación insegura?

Respuestas a la pregunta(1)

Su respuesta a la pregunta