假设这个简单的特征.暴露val x的特征.由于x的初始化成本非常高,因此我选择val x = …而不是def x = …
trait ScalaTrait {
self =>
val x: Int = SomeVeryExpensiveOperation.do()
}
现在,实现该特征的Java类怎么样.我当然必须在Java类中使用公共方法来实现val x.但这很重要:因为public方法和我的trait的val x具有相同的名称,所以我不能仅仅委托给trait实现:
class JavaClass imlements ScalaTrait {
@Override
public x() {
/* I can't hand over this call to x() of the trait,
since this would be a recursive call inside the Java class itself*/
return x(); <-- so, this no can do!
}
}
我的问题是方法x()中到底应该放什么?
或者,我可以为该私有val x字段提供一个公共def访问器.像这样:
trait ScalaTrait {
self =>
private val _x: Int = SomeVeryExpensiveOperation.do()
def x = _x
}
但是仍然,无论私有访问修饰符如何,我现在都必须在我的Java类中实现该私有val _x.我该如何工作?为什么我的Java类必须首先实现private val字段?
解决方法:
您真的不想要这样做.您将不得不深入研究Scala如何实现mixin并手动在Java中重新实现它.
这是一个简单的示例,全部在Scala中进行:
trait X {
val x = 5
}
class Y extends X
我们可以使用scalac -Xprint:mixin在Scala编译过程中获得一个中间阶段,该阶段显示了Scala为实现Y所做的工作:
[[syntax trees at end of mixin]] // test20.scala
package <empty> {
abstract trait X extends Object {
<accessor> def X$_setter_$x_=(x$1: Int): Unit;
<stable> <accessor> def x(): Int
};
class Y extends Object with X {
<stable> <accessor> def x(): Int = Y.this.x;
private[this] val x: Int = _;
<accessor> def X$_setter_$x_=(x$1: Int): Unit = Y.this.x = x$1;
def <init>(): Y = {
Y.super.<init>();
X$class./*X$class*/$init$(Y.this);
()
}
};
abstract trait X$class extends {
def /*X$class*/$init$($this: X): Unit = {
$this.X$_setter_$x_=(5);
()
}
}
}
您必须用Java手动实现所有有关Y的东西.您需要定义字段(x),访问器方法(也x),setter方法(X $_setter_ $x_),并将调用放入构造函数中的X $class.$init $.