Как абстрактное переопределение работает в терминах Java-кода? - PullRequest
4 голосов
/ 28 февраля 2012

Я нашел отличное объяснение того, как trait компилируется в код Java , но я думаю, что в нем отсутствует функция "абстрактного переопределения". Какой код Java генерируется для этой функции?

1 Ответ

6 голосов
/ 29 февраля 2012

Вот оно:

Короче говоря, abstract override def m() позволяет вызывать super.m() из метода, и этот супер-вызов динамически ограничивается вместо создания типа, когда черта смешивается после всех других типов, например

trait Printer {
  def print(msg: String)
}

trait Shouter extends Printer {
  abstract override def print(msg: String) { super.print(msg + "!") }
}

class ConsolePrinter extends Printer {
  def print(msg: String) { println(msg) }
}

val loudPrinter = new ConsolePrinter with Shouter

loudPrinter.print("Scala is great")

Здесь мы добавляем Shouter позже, после линеаризации типа он становится 'Shouter extends ConsolePrinter', а вызов super.print() становитсяConsolePrinter.print() и это дает нам:

Scala is great!

Google больше за «шаблон стека», это отличная вещь!:)

Ооо ... Я забыл про Java:)

Для данного примера у нас будет Shouter.class - интерфейс Shouter с методами:

  [0] Shouter$$super$print
  [1] print

Далее, Shouter $ class.class - конкретный класс с именем «Shouter $ class» со статическим методом print(LShouter;Ljava/lang/String;)V и телом:

 0 aload_0
 1 new #8 <scala/collection/mutable/StringBuilder>
 4 dup
 5 invokespecial #12 <scala/collection/mutable/StringBuilder.<init>>
 8 aload_1
 9 invokevirtual #16 <scala/collection/mutable/StringBuilder.append>
12 ldc #18 <!>
14 invokevirtual #16 <scala/collection/mutable/StringBuilder.append>
17 invokevirtual #22 <scala/collection/mutable/StringBuilder.toString>
20 invokeinterface #28 <Shouter.Shouter$$super$print> count 2
25 return

То есть вызов метода Shouter$$super$print(String) в переданном экземпляре.

Далее $$anon$1.class - конкретный класс с именем "$ anon $ 1" - это наш new ConsolePrinter with Shouter.Он реализует интерфейс Shouter, то есть его методы реализованы.И здесь:

print(Ljava/lang/String;)V

0 aload_0
1 aload_1
2 invokestatic #21 <Shouter$class.print>
5 return

Shouter$$super$print(Ljava/lang/String;)V:

0 aload_0
1 aload_1
2 invokespecial #11 <ConsolePrinter.print>
5 return

То есть в вызываемом print() мы вызываем static Shouter$class.print(), который является реализацией из черты Shouter.Эта печать добавляет ! и вызывает Shouter $$ super $ print () для нашего объекта, и мы пересылаем вызов ConsolePrinter.

Вот оно.

...