logo ejemplos chartjs chart scala reference compilation

ejemplos - Scala y referencias



hbase (4)

Posible duplicado:
Scala: referencias hacia adelante, ¿por qué se compila 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(b.a) } }

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


Como dice @paradigmatic, no es realmente un error. Es el orden de inicialización, que sigue al orden de declaración. En este caso, a es nulo cuando b se declara / init-ed.

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

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


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 sería la inicialización de las variables en línea, y dado que aún no se había definido, no se pudo compilar. Sin embargo, en Scala es más equivalente a 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, puede hacer que su declaración de b perezosa, lo que diferiría la configuración del valor hasta que se llame (en cuyo momento se habrá establecido una).


No es un error, sino un error clásico al aprender Scala. Cuando el objeto Omg se inicializa, 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 delante de la declaración a la que está haciendo 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(b.a) } }

El valor a se inicializará a petición.

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 son seguros para subprocesos.


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

Spec 5.1 para declaraciones de cuerpo de plantilla ejecutadas en orden; A partir de 4.0 para referencias hacia adelante en bloques.

Referencias hacia adelante: ¿por qué se compila este código?