Skip to content

Files

Latest commit

5301689 · Jan 7, 2018

History

History
49 lines (37 loc) · 2.28 KB

case_class.adoc

File metadata and controls

49 lines (37 loc) · 2.28 KB

Case Class

Case Classes 是 Scala 中最有用的编译器技巧之一。 它们本身不是很复杂,能帮助实现非常乏味和无聊的 equalshashCodetoString 等方法, 还可以配合模式匹配调用 apply/unapply 方法等等。

在 Scala 中可以像定义普通类一样定义一个 case class,但是需要加上 case 关键字:

case class Circle(radius: Double)

只需要这一行代码,我们就实现了 Value Object 模式。 定义了这样一个 case class 意味着我们自动得到了这些好处:

  • case class 的实例是不可变的(immutable)

  • 可以使用 equals 进行比较,并且相等性是基于字段的(*而不是*像普通类那样比较对象相等性)

  • 它的 hashcode 遵循 equals 合同,也是基于这个类的字段

  • 它的构造方法参数自动成为 public val 而无需声明(例如上面例子中的 radius

  • 它的 toString 是由类名和它所包含的字段的值组成的(对于我们的 Circle,toString 实现为 def toString = s"Circle($radius)")。

是时候总结一下我们学到的,然后应用到"现实生活"的例子中, 这一次我们要实现一个 Point 类,因为我们需要多于一个字段才能展示 case class 为我们提供的一些有趣特性:

case class Point(x: Int, y: Int)      (1)
val a = Point(0, 0)                   (2)
// a.toString == "Point(0,0)"         (3)

val b = a.copy(y = 10)                (4)
// b.toString == "Point(0,10)"

a == Point(0, 0)                      (5)
  1. xy 被自动地定义成 val 成员

  2. 同时会生成一个 Point 伴生对象,带有 apply(x: Int, y: Int) 方法,可以用来创建一个 Point 实例

  3. 自动生成的 toString 方法包含类名和参数值

  4. copy(…​) 方法允许通过仅改变选择的字段轻松创建派生对象

  5. case class 的相等性是基于值的(equals 和 hashCode 是根据 case class 的参数生成的)

不仅如此,case classes 还可以用于_模式匹配_,不论是"普通"还是"提取器(extractor)"语法(赋值给:)

Circle(2.5) match {
  case Circle(r) => println("Radius = " + r)
}

val Circle(r) = Circle(4.0)
val r2 = r * r // r2 现在是 16.0