4

I found a great explanation of how trait is compiled to Java code, but I think it is missing an "abstract override" feature. What Java code is generated for this feature?

Community
  • 1
  • 1
yura
  • 14,489
  • 21
  • 77
  • 126
  • Also take a lookt at this answer http://stackoverflow.com/questions/7637752/using-scala-traits-with-implemented-methods-in-java – tuxSlayer Feb 28 '12 at 21:17

1 Answers1

6

Here it comes:

It short, abstract override def m() allows to call super.m() from the method and this super call bounds dynamicaly in place of type creation, when a trait is mixing-in after all other types, for example

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")

Here we are mixing-in Shouter later, after type linearisation it becomes 'Shouter extends ConsolePrinter', and a call to super.print() becomesConsolePrinter.print() and it gives us:

Scala is great!

Google more for "stackable trait pattern", it's a great thing! :)

Agh... I forgot about Java :)

For a given example, we'll have Shouter.class - interface Shouter with methods:

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

Next, Shouter$class.class - concrete class named "Shouter$class" with static method print(LShouter;Ljava/lang/String;)V and the body:

 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

That is, calling method Shouter$$super$print(String) on passed instance.

Next, $$anon$1.class - concrete class named "$anon$1" - this is our new ConsolePrinter with Shouter. It implements interface Shouter, that is, have it methods implemented. And here:

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

That is, in called print() we're calling static Shouter$class.print() which is an implementation from Shouter trait. That print adds ! and calls Shouter$$super$print() on our object and we forward call to ConsolePrinter.

Here is it.

Community
  • 1
  • 1
tuxSlayer
  • 2,804
  • 2
  • 20
  • 24