Java类中的Scala getter和setter

fik*_*nik 11 java scala getter-setter scala-java-interop

我想创建一个遵循Scala setters/getters约定的Java类.

我试过跟随简单的类,但它不起作用:

public class JavaA {
private int a = 0;

public int a() {
    return a;
}

public void a_$eq(int a) {
    this.a = a;
}
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试从scala访问它时:

val x = new JavaA
x.a = 1
Run Code Online (Sandbox Code Playgroud)

我得到"重新分配给val"错误消息.我试图寻找这个,但是我发现了从scala到java的另一个问题.

做正确的方法是什么?

谢谢!

Rex*_*err 13

你只能这样做,而你可能不想这样做很难.

不能做的是写一个神奇的Java类,它被神奇地解释为Scala getter和setter.原因是Scala将信息嵌入到其getter和setter所需的类文件中(例如,有零参数块或一个空参数块 - 这种区别在JVM(或Java)中没有保留).

可以做的是使用Java来实现Scala定义的接口(即trait):

// GetSetA.scala
trait GetSetA { def a: Int; def a_=(a: Int): Unit }

// JavaUsesGSA.java
public class JavaUsesGSA implements GetSetA {
  private int a = 0;
  public int a() { return a; }
  public void a_$eq(int a) { this.a = a; }
}
Run Code Online (Sandbox Code Playgroud)

即使如此,你不能做的就是直接使用该类(同样是因为Java没有为Scala添加适当的注释信息):

scala> j.a = 5
<console>:8: error: reassignment to val
       j.a = 5
Run Code Online (Sandbox Code Playgroud)

但是因为它确实成功地实现了特征,所以当它被输入特征时你可以根据需要使用它:

scala> (j: GetSetA).a = 5
(j: GetSetA).a: Int = 5
Run Code Online (Sandbox Code Playgroud)

所以这是一个混合包.通过任何方式都不完美,但在某些情况下可能有足够的功能来帮助.

(另一种选择当然是提供从Java类到具有引用Java类的实际方法的getter/setter的隐式转换;即使您不能从Scala继承Java,这也是有效的.)

(编辑:当然没有关键的原因,编译器必须以这种方式行事;有人可能会认为解释Java定义的getter/setter对就好像它们是Scala那样(即如果类文件没有明确地说它来自Scala)是一个功能增强的良好候选者,以提高Java互操作性.)