2012-01-05 6 views
11

Nelle versioni di Scala precedenti alla 2.9.0, le implementazioni di funzioni concrete nei tratti venivano compilate come metodi normali. A partire dal 2.9.x in poi, vengono compilati come metodi ponte. Sto cercando di trovare il ragionamento dietro questo cambiamento, perché influisce negativamente sugli utenti di molti framework Java popolari come Spring e Jersey.Perché le implementazioni di funzioni concrete in tratti sono compilate per il bridge di metodi in Scala 2.9.x ma non in 2.8.x?

Si consideri il seguente codice Scala:

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

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

Quando la classe Dog viene compilato con scalac versione 2.8.1 e decompilato con javap, il risultato per le funzioni di "parlare" e "wag" simile a questa:

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 

quando il cane è compilato con scalac versione 2.9.1 e ancora una volta decompilato, le stesse due funzioni assomigliano:

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 problematica è l'aggiunta del flag ACC_BRIDGE alla funzione speak(). Strutture come Jersey e Spring intenzionalmente non riconoscono i metodi bridge in molti casi come soluzioni alternative per altri problemi.

Quindi qualcuno può spiegare o indicare una buona spiegazione del motivo per cui questa modifica è stata apportata in Scala 2.9.x?

Come seguito, c'è un modo per disabilitare questo comportamento attraverso una funzione annotazione, flag del compilatore, ecc.?

+3

Domanda interessante ma, come molte di queste domande di design, potrebbe sii meglio [prima] chiesto su ML (e poi trapiantato/focalizzato qui). Per esempio. l'eventuale domanda SO potrebbe essere "Come posso ottenere che Spring riconosca ..." –

risposta