Pregunta

Soy nuevo en scala de java y estoy confundido por la secuencia de inicialización de objetos de scala en una jerarquía inherente. IIRC, en Java, si se inicializa un objeto de subclase, se invoca el constructor de su clase base antes que cualquier código de su propio constructor. Mientras estoy en Scala, obtengo un comportamiento totalmente diferente. Considere el siguiente ejemplo:

class Point(val x: Int, val y: Int){
    val name = this.makeName;

    def makeName: String = {
        println("makeName at super.");

        "[" + x + ", " + y + "]";
    }

    override def toString: String = name;
}

class ColorPoint(override val x: Int, override val y: Int, var color: String) extends Point(x, y) {

    // key statement
    println(name);

    override def makeName: String = {
        println("makeName at sub.");

        super.makeName + ":" + myColor;
    }

    val myColor = color;

    override def toString: String = name;
}

Consideremos el código de bytes del constructor de ColorPoint volcado con javap. Si el código incluye la declaración clave println(name);, el código de bytes es

public ColorPoint(int, int, java.lang.String);
  Code:
   0:   aload_0
   1:   aload_3
   2:   putfield        #13; //Field color:Ljava/lang/String;
   5:   aload_0
   6:   iload_1
   7:   iload_2
   8:   invokespecial   #18; //Method Point."<init>":(II)V
   11:  getstatic       #24; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   14:  aload_0
   15:  invokevirtual   #28; //Method name:()Ljava/lang/String;
   18:  invokevirtual   #32; //Method scala/Predef$.println:(Ljava/lang/Object;)V
   21:  aload_0
   22:  aload_3
   23:  putfield        #34; //Field myColor:Ljava/lang/String;
   26:  return

Podemos ver que el campo myColor se inicializa después de invokespecial, es decir, después de la inicialización de la clase base.

Si comento la declaración println(name);, el código de bytes es:

public ColorPoint(int, int, java.lang.String);
  Code:
   0:   aload_0
   1:   aload_3
   2:   putfield        #13; //Field color:Ljava/lang/String;
   5:   aload_0
   6:   aload_3
   7:   putfield        #15; //Field myColor:Ljava/lang/String;
   10:  aload_0
   11:  iload_1
   12:  iload_2
   13:  invokespecial   #20; //Method Point."<init>":(II)V
   16:  return

Vemos que el campo myColor se inicializa justo antes de invokespecial, es decir, antes de que se inicialice la base.

Entonces, ¿cuál es el motivo? ¿Algún documento / artículo especifica este tipo de comportamiento?

Por cierto, la versión de mi scala es 2.7.7final (OpenJDK Server VM, Java 1.6.0_20). ¡Gracias y saludos cordiales!

¿Fue útil?

Solución

El compilador simplemente está ejecutando las cosas en orden.Hay algo de documentación aquí.

https://github.com/paulp/scala-faq/wiki/Orden de inicialización

La parte principal es la siguiente.

  1. Las superclases se inicializan completamente antes que las subclases.
  2. De lo contrario, en orden de declaración.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top