[英]Understanding Case class and Traits in Scala
我有一个如下定义的简单特征:
trait MyTrait {
def myStringVal: String
}
我的case类实现了这个特性如下:
case class MyCaseClass(myStringVal: String) extends MyTrait {
...
...
}
来自Java世界,我发现有点难以理解MyCaseClass实际上只是通过定义MyCaseClass的参数来实现它。 我知道你的字节代码实际上会编写getter和setter。 但如果没有var或val,这怎么可能呢?
我的理解是,如果没有var或val,则不会生成getter或setter方法。 在这种情况下,上面的案例类MyCaseClass如何实现myStringVal方法?
有时太多的Scala魔法难以理解,特别是遗留代码。
您可能希望查看此博客文章,其中涵盖了具体类型以及它们如此有用的原因。
在您的示例中,特性MyTrait
没有用,除了能够像java接口一样运行。 请注意,scala中的默认可见性是公共的。 默认情况下,case类参数是不可变的,因此在您的示例中, val
会由编译器自动推断为myStringVal
参数。
案例课有什么神奇之处 ?!
val
) toString()
, equals()
和hashcode()
方法 apply()
和unapply()
方法,它们基本上只是一个方便构造函数,允许在不使用new
关键字的情况下实例化,并且默认情况下会生成一个包含选项包装的case类的tuple
参数。 编辑:(案例)类的示例编译器输出(从scalatutorial.de复制)
一个简单的scala类定义
class A1(v1: Int, v2: Double)
被编译为java代码
public class A1 extends java.lang.Object implements scala.ScalaObject {
public A1(int, double);
}
类似的案例类
case class A2(v1: Int, v2: Double)
被编译为以下java类
public class A2 extends java.lang.Object implements
scala.ScalaObject,scala.Product,java.io.Serializable {
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 double copy$default$2();
public int copy$default$1();
public int v1();
public double v2();
public A2 copy(int, double);
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);
public A2(int, double);
}
public final class A2$ extends scala.runtime.AbstractFunction2
implements scala.ScalaObject {
public static final A2$ MODULE$;
public static {};
public scala.Option unapply(A2);
public A2 apply(int, double);
public java.lang.Object apply(java.lang.Object, java.lang.Object);
}
Scala案例类为您实现了大量的样板,并且将所有构造函数参数自动暴露为val
这是其中之一。
如果你试图在常规类中避免使用val
,那样:
trait MyTrait {
def myVal: String
}
class MyClass(myVal: String) extends MyTrait
编译器将显示错误消息,MyClass必须是抽象的,因为它不会覆盖myVal
方法,但是将val
或var
添加到类构造函数参数将解决问题。
案例类是不同的 - 为它们生成了一些默认方法。 这包括参数的val getters。 将案例类视为POJO - 这是一个有用的语法糖,因为它们不需要私有成员。
unapply
生成一些其他有用的方法,例如copy
, toString
, apply
和unapply
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.