2012-01-05 9 views
11

En las versiones de Scala anteriores a la 2.9.0, se compilaron implementaciones de funciones concretas en rasgos como métodos normales. A partir de 2.9.x en adelante, se compilan como métodos de puente. Estoy tratando de encontrar el razonamiento detrás de este cambio, ya que afecta negativamente a los usuarios de muchos frameworks populares de Java como Spring y Jersey.¿Por qué las implementaciones de funciones concretas en rasgos se compilan para puentear métodos en Scala 2.9.x pero no en 2.8.x?

Considere el siguiente código Scala:

trait Speaks { 
    def speak() = { 
    println("woof") 
    } 
} 

class Dog extends Speaks { 
    def wag() = { 
    println("wag wag") 
    } 
} 

Cuando la clase de perro se compila con la versión 2.8.1 y scalac decompiled con javap, el resultado de las funciones y "hablar" "meneo" se parece a esto:

public void speak(); 
    flags: ACC_PUBLIC 
    Code: 
     stack=1, locals=1, args_size=1 
     0: aload_0  
     1: invokestatic #11     // Method Speaks$class.speak:(LSpeaks;)V 
     4: return   
     LineNumberTable: 
     line 7: 0 

public void wag(); 
    flags: ACC_PUBLIC 
    Code: 
     stack=2, locals=1, args_size=1 
     0: getstatic  #18     // Field scala/Predef$.MODULE$:Lscala/Predef$; 
     3: ldc   #20     // String wag wag 
     5: invokevirtual #24     // Method scala/Predef$.println:(Ljava/lang/Object;)V 
     8: return   
     LineNumberTable: 
     line 9: 0 

Cuando el perro se compila con la versión 2.9.1 scalac y otra vez decompiled, las mismas dos funciones parecen:

public void speak(); 
    flags: ACC_PUBLIC, ACC_BRIDGE 
    Code: 
    stack=1, locals=1, args_size=1 
     0: aload_0  
     1: invokestatic #11     // Method Speaks$class.speak:(LSpeaks;)V 
     4: return   
    LineNumberTable: 
     line 7: 0 

public void wag(); 
    flags: ACC_PUBLIC 
    Code: 
    stack=2, locals=1, args_size=1 
     0: getstatic  #18     // Field scala/Predef$.MODULE$:Lscala/Predef$; 
     3: ldc   #20     // String wag wag 
     5: invokevirtual #24     // Method scala/Predef$.println:(Ljava/lang/Object;)V 
     8: return   
    LineNumberTable: 
     line 9: 0 

La parte problemática es la adición del indicador ACC_BRIDGE a la función speak(). Los marcos como Jersey y Spring intencionalmente no reconocen los métodos de puente en muchos casos como soluciones para otros problemas.

Entonces, ¿alguien puede explicar o señalar una buena explicación de por qué se realizó este cambio en Scala 2.9.x?

Como seguimiento, ¿hay alguna forma de deshabilitar este comportamiento mediante una anotación de función, un indicador de compilación, etc.?

+3

pregunta interesante pero, al igual que muchas de estas cuestiones de diseño, podría ser mejor [primero] preguntado sobre ML (y luego transplantado/enfocado aquí). P.ej. la eventual pregunta SO podría ser "¿Cómo puedo lograr que Spring reconozca ...?" –

Respuesta

Cuestiones relacionadas