Scala y referencias hacia adelante

Posible duplicado:
Scala: referencias directas: ¿por qué comstack este código?

object Omg { class A class B(val a: A) private val b = new B(a) private val a = new A def main(args: Array[String]) { println(ba) } } 

el siguiente código imprime “nulo”. En java construcción similar no se comstack debido a una referencia directa no válida. La pregunta es: ¿por qué comstack bien en Scala? ¿Es eso por diseño, descrito en SLS o simplemente error en 2.9.1?

No es un error, sino un error clásico al aprender a Scala. Cuando se inicializa el objeto Omg , todos los valores se establecen primero en el valor predeterminado ( null en este caso) y luego se ejecuta el constructor (es decir, el cuerpo del objeto).

Para que funcione, simplemente agregue la palabra clave lazy al frente de la statement a la que hace referencia (valor a en este caso):

 object Omg { class A class B(val a: A) private val b = new B(a) private lazy val a = new A def main(args: Array[String]) { println(ba) } } 

El valor a se inicializará bajo demanda.

Esta construcción es rápida (los valores solo se inicializan una vez para todo el tiempo de ejecución de la aplicación) y es segura para la ejecución de subprocesos.

La forma en que lo entiendo, tiene que ver con la forma en que se crean las clases de Scala. En Java, la clase definida anteriormente estaría inicializando las variables en línea, y como a aún no se había definido, no podría comstackrse. Sin embargo, en Scala es más el equivalente de esto en Java (que también debería producir nulo en el mismo escenario):

 class Omg { private B b = null; private A a = null; Omg(){ b = new B(a); a = new A(); } } 

Alternativamente, podría hacer su statement de b perezoso, lo que diferiría estableciendo el valor hasta que se llame (en ese momento se habrá establecido un valor).

Si esto es una preocupación, compile con -Xcheckinit durante el desarrollo y repita hasta que las excepciones desaparezcan.

Espec 5.1 para las sentencias del cuerpo de la plantilla ejecutadas en orden; comienzo de 4.0 para referencias hacia adelante en bloques.

Referencias a futuro: ¿por qué comstack este código?

Como @paradigmatic states, no es realmente un error. Es el orden de inicialización, que sigue el orden de la statement. En este caso, a es nulo cuando b se declara / inicia.

Cambiar la línea private val b = new B(a) a private lazy val b = new B(a) solucionará el problema, ya que usar perezoso retrasará el init. de b a su primer uso.

Es muy probable que este comportamiento se describa en el SLS.