您的位置:

Case Class详解

一、什么是Case Class

Case Class是Scala中一种特殊的类,用来存储不可变的数据,它是一个不可变的值对象,自带equals、hashCode、toString等方法。而且Case Class定义的对象可以通过模式匹配来进行操作,这使得Case Class非常适合用于模式匹配,对于模式匹配的情况,最重要的是能够让你检查编译时的错误。

Case Class有以下几个特点:

  • 编译器会自动为Case Class生成构造函数
  • 自动实现equals()、hashCode()、toString()等方法
  • 可以使用模式匹配(Pattern Matching)匹配各个属性
  • 可以使用copy()方法复制对象(新的对象与源对象属性值相同,没有改变源对象)
case class Person(name: String, age: Int)
val p1 = Person("张三", 20)
val p2 = Person("李四", 30)
println(p1.equals(p2)) // false
println(p1) // Person(张三,20)

val p3 = p1.copy(name = "王五")
println(p3) // Person(王五,20)

二、Case Class的构造函数

使用Case Class定义一个不可变的类,可以通过构造函数初始化。

默认情况下,构造函数的参数列表会被自动声明为类的字段。Case Class比一般类更容易创建,因为它还可以省略new关键字。但是它也支持new关键字进行对象初始化创建。

case class Person(name: String, age: Int, gender: String)

// 使用构造函数初始化对象
val person1 = Person("小明", 10, "男")
println(person1.name) // 小明
println(person1.age) // 10
println(person1.gender) // 男

// 使用new关键字初始化对象
val person2 = new Person("小红", 12, "女")
println(person2.name) // 小红
println(person2.age) // 12
println(person2.gender) // 女

三、Case Class的模式匹配

Case Class最大的特点之一就是可以使用模式匹配来操作它,模式匹配也是Scala中非常强大和灵活的一个特性。通过模式匹配可以匹配某个变量的值,并根据值的不同执行不同的操作。

case class Person(name: String, age: Int)
val p = Person("小明", 18)

// 匹配name为"小明",age为18的实例
p match {
  case Person("小明", 18) => println("匹配成功")
  case _ => println("没有匹配")
}

四、Case Class的copy()

在Case Class中,我们可以通过copy()方法复制对象(新的对象与源对象属性值相同,没有改变源对象),然后可以通过修改复制后对象的属性值得到一个新的对象。

case class Person(name: String, age: Int)
val p1 = Person("小明", 18)
val p2 = p1.copy(name = "小红")

println(p1) // Person(小明,18)
println(p2) // Person(小红,18)

五、Case Class的嵌套使用

Case Class支持使用其他的Case Class对象作为它的属性,从而实现更加复杂的数据结构定义。也就是说,Case Class可以被嵌套到另一个Case Class中。

case class Person(name: String, age: Int)
case class Book(name: String, author: Person)

val author = Person("小明", 18)
val book = Book("《Scala编程》", author)

println(book.author.name) // 小明

六、Case Class的注解

Case Class也可以使用注解,如@SerialVersionUID注解可以为Case Class生成serialVersionUID。

import java.io.Serializable
import scala.beans.BeanProperty
import scala.annotation.meta.field

@SerialVersionUID(1000L)
case class Person(@(BeanProperty @field)name: String, age: Int) extends Serializable

val p = Person("小明", 18)
println(p.serialVersionUID) // 1000

七、Case Class的不可变性

Case Class是不可变的,一旦它被创建,它的所有属性值就不能再次更改。试图在创建后更改Case Class对象的值会导致编译器错误。

case class Person(name: String, age: Int)
val p = Person("小明", 18)

// 编译器出现错误
// p.age = 19

八、Case Class的继承

Case Class可以继承其他类,但是遵循以下规则:

  • case class和普通class在概念上不同,不能继承case class
  • case class可以继承其他的case class
  • case class的继承者必须仍是Case Class,否则子类所继承的auto-generation实现的特性被丧失。
abstract class Human(name: String, age: Int)
case class Person(name: String, age: Int) extends Human(name, age)

val p = Person("小明", 18)
println(p.name) // 小明