0

次の(明らかにゴミのような)コードが示すようなことをしたいと思います:

// Clearly nonsensical
case class Example(a: String) {
    def a: Array[Byte] = a.getBytes
}

その要点は、コンストラクター引数の 1 つと同じ名前のケース クラスのアクセサー メソッドを書きたいということです。

Jerksonと呼ばれる JSON シリアライゼーション ライブラリを使用しています。これは、私の理解によれば、この方法でクラスを定義すると、希望どおりに動作します。私はこのコードにその仮定を基にしています。現在、私は困惑しています。

これが不可能な場合、Jerkson ライブラリ コードが何をしようとしているのかについて誰か洞察を提供できますか?

4

2 に答える 2

3

Scalaは、参照透過性valと呼ばれる概念をサポートするために、クラス(ケースクラスのフィールドを含む)で宣言されたものと同じ名前のメソッドを自動的に作成します。これは、をでオーバーライドできる理由でもあります。それでも懐疑的な場合は、次のように自分でテストできます。defval

まず、単一のケースクラスでScalaファイルを作成します。

// MyCase.scala
case class MyCase(myField1: Int, myField2: String)

ここで、を使用してファイルをコンパイルしますscalac。これにより、2つのクラスが作成されます。上記の例では、MyCase.class(実際のケースクラスタイプを表す)とMyCase $ .class(ケースクラスの自動生成されたコンパニオンオブジェクトを表す)を取得します。

$ scalac MyCase.scala 
$ ls
MyCase$.class MyCase.class  MyCase.scala

.classこれで、を使用して宣言したケースクラスに対応する結果のファイルを調べることができますjavap。(javapJavaバイトコードを調べるための標準ツール-JDKで一緒に配布されjavacます。)

$ javap -private MyCase
Compiled from "MyCase.scala"
public class MyCase extends java.lang.Object implements scala.Product,scala.Serializable{
    private final int myField1;
    private final java.lang.String myField2;
    public static final scala.Function1 tupled();
    public static final scala.Function1 curry();
    public static final scala.Function1 curried();
    public scala.collection.Iterator productIterator();
    public scala.collection.Iterator productElements();
    public int myField1();
    public java.lang.String myField2();
    public MyCase copy(int, java.lang.String);
    public java.lang.String copy$default$2();
    public int copy$default$1();
    public int hashCode();
    public java.lang.String toString();
    public boolean equals(java.lang.Object);
    public java.lang.String productPrefix();
    public int productArity();
    public java.lang.Object productElement(int);
    public boolean canEqual(java.lang.Object);
    private final boolean gd1$1(int, java.lang.String);
    public MyCase(int, java.lang.String);
}

結果のクラスに、ケースクラスのフィールドに対応するprivate final int myField1との両方があることに注意してください。についても同じです。public int myField1()myField1myField2

JVMメソッドでは、リターンタイプはメソッドシグネチャの一部ではありません。これは、2つのメソッドが同じ名前と同じ引数タイプを持っている場合、それらは競合するメソッド宣言であると見なされることを意味します。これは、引数をとらずにすでに存在def a: Array[Byte]しているため、例でを宣言できないことを意味します。val a: String

アップデート:

ライブラリコードを見たところ、例によれば、ケースクラスは正常に機能するはずです。READMEには、ケースクラスの解析はREPLでは機能しないという注記があります。それがあなたの問題でしょうか?そうでない場合は、実際に発生しているエラーを投稿する必要があります。編集:気にしないでください、私はあなたがあなたの他の投稿へのあなたのリンクであなたが話しているエラーを見ます。その問題への対応を考えたら、あそこに投稿します。

于 2012-08-24T09:17:44.243 に答える
3

いいえ、できません。その理由は、caseクラスのコンストラクター引数は、で宣言した場合のように、自動的にパブリック値になるためですvalA Tour of Scala: Case Classesを引用するには

ケース クラスのコンストラクター パラメーターはパブリック値として扱われ、直接アクセスできます。

したがって、各コンストラクター引数に対して、Scala は対応するアクセサー メソッドを同じ名前で作成します。同じ名前のメソッドを作成することはできません。既に存在しています。

これは実際にcaseクラスが何であるかです。それらはパターン マッチングに使用できるため、それらから取得される値は、それらを構築するために使用される値と同じである必要があります。

(クラスを使用することが要件caseですか?通常のクラスを使用すると問題が解決するようです。)

于 2012-08-24T07:01:16.137 に答える