特征:Scala和Java之间的互操作,从Java访问val

时间:2014-06-03 23:02:58

标签: java scala interop traits

假设这个简单的特征。暴露 val x 的特征。由于 x 的初始化成本非常高,我选择 val x = ... 而不是 def x = ...

trait ScalaTrait {

  self =>

  val x: Int = SomeVeryExpensiveOperation.do()

}

现在,如何实现这个特性的Java类。我当然不得不在我的Java类中使用公共方法实现 val x 。但是这里有一个问题:因为公共方法和我的特征的 val x 共享相同的名称,我不能只委托给特征实现:

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 字段?

1 个答案:

答案 0 :(得分:3)

你真的不想这样做。您将不得不深入了解Scala如何实现mixins并在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);
      ()
    }
  }
}

Y的所有内容你将不得不用Java手工实现。您需要定义字段(x),访问器方法(也是x),setter方法(X$_setter_$x_),并在构造函数中调用X$class.$init$