0

我想我希望能够做如下(显然是垃圾)代码所示的事情:

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

它的要点是我想为一个与它的构造函数参数之一命名相同的案例类编写一个访问器方法。

我正在使用一个名为Jerkson的 JSON 序列化库,根据我的理解,如果我以这种方式定义一个类,它将按照我想要的方式运行。我基于此代码的假设。目前,我很难过

如果这是不可能的,任何人都可以提供一些关于 Jerkson 库代码试图做什么的见解吗?

4

2 回答 2

3

不,这是不可能的。原因是case类的构造函数参数自动成为公共值,就像你用val. 引用Scala 之旅:案例类

案例类的构造函数参数被视为公共值,可以直接访问。

因此,Scala 为每个构造函数参数创建一个对应的同名访问器方法。您不能创建具有相同名称的方法,它已经存在。

这实际上就是case课程的意义所在。想法是它们可以用于模式匹配,因此从它们检索的值应该与用于构造它们的值相同。

(使用类是要求case吗?使用常规类似乎可以解决问题。)

于 2012-08-24T07:01:16.137 回答
3

valScala 自动创建一个与类中声明的任何方法(包括案例类的字段)同名的方法,以支持称为引用透明性的概念。这也是您可以用 a覆盖 adefval的原因。如果您仍然持怀疑态度,您可以像这样自己测试:

首先,创建一个包含单个案例类的 Scala 文件。

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

现在,用scalac. 这应该导致两个类。对于上面的示例,我得到MyCase.class(代表实际案例类类型)和MyCase$.class(代表案例类的自动生成的伴随对象)。

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

现在您可以检查与.class您使用声明的案例类相对应的结果文件javap。(javap检查 Java 字节码的标准工具——它与javacJDK 一起分发。)

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

请注意生成的类如何同时具有与案例类的字段对应的aprivate final int myField1和 a 。对于.public int myField1()myField1myField2

在 JVM 上,方法返回类型不是方法签名的一部分。这意味着如果两个方法具有相同的名称和相同的参数类型,那么它们被认为是冲突的方法声明。这意味着您不能def a: Array[Byte]在示例中声明,因为val a: String已经存在,也没有参数。

更新:

我只是查看了库代码,根据示例,案例类应该可以正常工作。README中有一条注释说解析案例类在 REPL 中不起作用。那会是你的问题吗?如果没有,您应该真正发布您遇到的错误。编辑:没关系,我在指向其他帖子的链接中看到了您所说的错误。如果我想到对该问题的回应,我会在那里发布。

于 2012-08-24T09:17:44.243 回答