为什么在trait中编译具体的函数实现以桥接Scala 2.9.x中的方法而不是2.8.x中的方法? [英] Why are concrete function implementations in traits compiled to bridge methods in Scala 2.9.x but not in 2.8.x?

查看:102
本文介绍了为什么在trait中编译具体的函数实现以桥接Scala 2.9.x中的方法而不是2.8.x中的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在2.9.0之前的Scala版本中,将traits中的具体函数实现编译为常规方法.从2.9.x开始,它们被编译为桥接方法.我试图找到这种变化背后的原因,因为它会对许多流行的Java框架(如Spring和Jersey)的用户产生负面影响.

In Scala versions prior to 2.9.0, concrete function implementations in traits were compiled as normal methods. From 2.9.x onward, they are compiled as bridge methods. I'm trying to find the reasoning behind this change, because it negatively affects users of many popular Java frameworks like Spring and Jersey.

考虑以下Scala代码:

Consider the following Scala code:

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

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

当Dog类使用scalac版本2.8.1编译并使用javap进行反编译时,"speak"和"wag"函数的结果如下所示:

When the Dog class is compiled with scalac version 2.8.1 and decompiled with javap, the result for the "speak" and "wag" functions look like this:

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编译Dog并再次对其进行反编译时,相同的两个函数如下所示:

When Dog is compiled with scalac version 2.9.1 and again decompiled, the same two functions look like:

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

有问题的部分是在talk()函数中添加了ACC_BRIDGE标志.诸如Jersey和Spring之类的框架在许多情况下故意不将桥接方法识别为解决其他问题的方法.

The problematic part is the addition of the ACC_BRIDGE flag to the speak() function. Frameworks like Jersey and Spring intentionally do not recognize bridge methods in many cases as workarounds for other issues.

因此,有人可以解释或指出为什么在Scala 2.9.x中进行了此更改吗?

So can anyone explain or point to a good explanation of why this change was made in Scala 2.9.x?

作为后续措施,是否可以通过函数注释,编译器标志等禁用此行为?

As a followup, is there a way to disable this behavior through a function annotation, compiler flag, etc?

推荐答案

好的,似乎没有解释为什么的原因,因为这不是有意更改.看到这个线程: http://groups.google.com/group/scala-language/browse_thread/thread/67f8884081d46912

OK it sounds like there is no explanation as to why because it wasn't an intentional change. See this thread: http://groups.google.com/group/scala-language/browse_thread/thread/67f8884081d46912

解决方案是使用最新的快照,或者,如果在您阅读本文时将来已到,则使用Scala 2.10

And the solution is to use the newest snapshot, or, if the future has arrived as you read this, Scala 2.10

这篇关于为什么在trait中编译具体的函数实现以桥接Scala 2.9.x中的方法而不是2.8.x中的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆