2.9.0より前のScalaバージョンでは、特性の具体的な関数実装は通常のメソッドとしてコンパイルされていました。 2.9.x以降では、ブリッジメソッドとしてコンパイルされます。 SpringとJerseyのような人気の高いJavaフレームワークのユーザーに悪影響を与えるため、この変更の背後にある理由を見つけようとしています。 Dogクラスはscalacバージョン2.8.1でコンパイルしてjavapで逆コンパイルされたときに、「話す」と「WAG」機能のための結果は次のようになり特性の具体的な関数実装がScala 2.9.xのメソッドをブリッジするようにコンパイルされているのはなぜですか?
trait Speaks {
def speak() = {
println("woof")
}
}
class Dog extends Speaks {
def wag() = {
println("wag wag")
}
}
:
は以下のScalaのコードを考えてみましょう。
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
犬はscalacバージョン2.9.1でコンパイルされ、再び逆コンパイルされた場合、同じ2つの関数は次のようになります。
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
問題のある部分は、speak()関数にACC_BRIDGEフラグを追加したことです。 JerseyやSpringのようなフレームワークは、他の問題の回避策として、多くの場合ブリッジメソッドを意図的に認識しません。
だから誰もこの変更がScala 2.9.xで行われた理由を説明することができますか?
次のように、関数の注釈、コンパイラフラグなどでこの動作を無効にする方法はありますか?
興味深い質問しかし、これらの設計の質問の多くのように:このスレッドを参照してください。最初にMLで尋ねられた方が良いです(そしてここで移植/焦点を合わせました)。例えば。結局のところ、SOの質問は "私は春に認識させることができますか?" –