我找到了 a great explanation of how trait is compiled to Java code ,但我认为它缺少“抽象覆盖”功能。为这个特性生成了什么 Java 代码?
最佳答案
它来了:
简而言之,
abstract override def m()
允许从方法调用 super.m()
并且这个 super 调用动态地限制在类型创建的位置,例如,当一个特征在所有其他类型之后混合时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!
谷歌更多的“可堆叠特征模式”,这是一件很棒的事情! :)
啊...我忘记了 Java :)
对于给定的示例,我们将拥有 Shouter.class - 带有方法的接口(interface) 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
。它实现了接口(interface)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()
,它是 Souter trait 的一个实现。该打印添加 !
并在我们的对象上调用 Shouter$$super$print() ,然后我们将调用转发到 ConsolePrinter。就这个。
关于scala - Java 代码中的抽象覆盖如何工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9476126/