11

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;
}
}

しかし、scalaからアクセスしようとすると:

val x = new JavaA
x.a = 1

「valへの再割り当て」エラーメッセージが表示されます。私はこれを探しようとしましたが、すべての問題は、scalaからjavaへの逆の場所で見つかりました。

それを行う正しい方法は何ですか?

ありがとう!

4

2 に答える 2

13

あなたはこれを行うことができるだけであり、おそらくあなたがしたくないほど難しいです。

あなたができないことは、魔法のようにScalaゲッターとセッターとして解釈される裸のJavaクラスを書くことです。その理由は、Scalaがゲッターとセッターに必要な情報をクラスファイルに埋め込むためです(たとえば、パラメーターブロックがゼロまたは空のパラメーターブロックが1つあります。この区別はJVM(またはJava)では保持されません)。

できることは、Javaを使用してScalaで定義されたインターフェース(つまり、特性)を実装することです。

// 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; }
}

それでも、クラスを直接使用することはできません(これも、JavaがScalaに適切なアノテーション情報を追加しないためです)

scala> j.a = 5
<console>:8: error: reassignment to val
       j.a = 5

ただし、トレイト正常に実装されるため、トレイトとして入力すると、必要に応じて使用できます。

scala> (j: GetSetA).a = 5
(j: GetSetA).a: Int = 5

ですから、それはむしろ混合バッグです。決して完璧ではありませんが、場合によっては十分に機能する可能性があります。

(もちろん、他の代替手段は、JavaクラスからJavaクラスの実際のメソッドを参照するゲッター/セッターを持つクラスへの暗黙の変換を提供することです。これは、JavaをScalaから継承させることができない場合でも機能します。 。)

(編集:もちろん、コンパイラーがこのように動作しなければならないという重大な理由はありません。Java定義のゲッター/セッターのペアをScalaのものであるかのように解釈する(つまり、クラスファイルがScalaからのものであると明示的に述べていない場合)と主張することができます。 Javaの相互運用性を改善するための機能拡張の良い候補です。)

于 2012-06-05T14:19:41.457 に答える
1

恐れ入りますが、できません。Scalaでは、アクセサーは、のようにパラメーターリストのないメソッドである必要がありますdef a = _a。たとえばScalaで書くdef a() = _aと同じエラーが発生し、Javaでパラメータリストのないメソッドを定義する方法はありません。独自のコンパイラを生成することでScalaコンパイラをだますことができるかもしれませScalaSignatureんが、それはおそらく問題の価値はありません…</ p>

于 2012-06-05T14:00:29.830 に答える