我有一个如下定义的简单特征:
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魔法难以理解,特别是遗留代码 .
3 回答
您可能希望查看this blog article,其中涵盖了具体类型以及它们如此有用的原因 .
在您的示例中,特性
MyTrait
没有用,除了能够像java接口一样运行 . 请注意,scala中的默认可见性是公共的 . 默认情况下,case类参数是不可变的,因此在您的示例中val
由编译器自动推断为myStringVal
参数 .案例课有什么神奇之处?!
默认字段将所有构造函数参数转换为public readonly(
val
)使用每种方法的所有构造函数参数生成
toString()
,equals()
和hashcode()
方法生成具有相同名称的伴随对象,其中包含适当的
apply()
和unapply()
方法,这些方法基本上只是一个方便构造函数,允许在不使用new
关键字的情况下实例化,并且提取器默认情况下生成一个包含选项的tuple
案例类参数 .EDIT: (案例)类的示例编译器输出(从scalatutorial.de复制)
一个简单的scala类定义
被编译为java代码
类似的案例类
被编译为以下java类
Scala案例类为您实现了大量的样板,并且所有构造函数参数都自动公开为
val
s就是其中之一 .如果您尝试在常规类中避免使用
val
,请执行以下操作:编译器将显示错误消息,MyClass必须是抽象的,因为它不会覆盖
myVal
方法,但是将val
或var
添加到类构造函数参数将解决该问题 .案例类是不同的 - 为它们生成了一些默认方法 . 这包括参数的val getters . 将案例类视为POJO - 这是一个有用的语法糖,因为它们不需要私有成员 .
还会生成一些其他有用的方法,例如
copy
,toString
,apply
和unapply
.