Почему конкретные реализации функций в чертах скомпилированы для соединения методов в Scala 2.9.x, а не в 2.8.x? - PullRequest
11 голосов
/ 05 января 2012

В версиях Scala до 2.9.0 конкретные реализации функций в чертах были скомпилированы как обычные методы.Начиная с версии 2.9.x они компилируются как методы моста.Я пытаюсь найти причину этого изменения, потому что оно отрицательно влияет на пользователей многих популярных Java-фреймворков, таких как Spring и Jersey.

Рассмотрим следующий код Scala:

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

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

КогдаКласс Dog скомпилирован с использованием скалярной версии 2.8.1 и декомпилирован с использованием javap, результат для функций «speak» и «wag» выглядит следующим образом:

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

Когда Dog компилируется с использованием версии 2.9 scalacи снова декомпилированные, эти же две функции выглядят так:

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

Проблемной частью является добавление флага ACC_BRIDGE к функции speak ().Фреймворки, такие как Джерси и Спринг, преднамеренно не распознают методы моста во многих случаях как обходные пути для других проблем.

Так может ли кто-нибудь объяснить или указать хорошее объяснение, почему это изменение было сделано в Scala 2.9.x?

Как продолжение, есть ли способ отключить это поведение с помощью аннотации функции, флага компилятора и т. Д.?

1 Ответ

7 голосов
/ 06 января 2012

ОК, похоже, нет объяснения, почему, потому что это не было преднамеренным изменением.Смотрите эту ветку: http://groups.google.com/group/scala-language/browse_thread/thread/67f8884081d46912

И решение состоит в том, чтобы использовать новейший снимок, или, если будущее настало, когда вы читаете это, Scala 2.10

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...