特性:Scala与Java之间的互操作,从Java访问val

假设这个简单的特征.暴露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 $.

上一篇:PHP:如何从当前类中使用的特征方法调用父方法?


下一篇:python-PyFace,TraitsUI和TraitsGUI