scala样例类
Scala 样例类(Case Class):模式匹配的完美搭档
样例类(Case Class)是 Scala 中一种特殊的类,专门为模式匹配和不可变数据建模设计。它自动生成了一系列常用方法,大幅简化了数据封装和匹配的代码。本文将详细解析样例类的特性、用法及适用场景。
样例类的定义与基本特性
样例类通过 case class 关键字定义,与普通类相比,它具有以下默认特性:
// 定义样例类(无需 new 关键字即可创建实例)
case class Student(id: Int, name: String, age: Int)
// 创建实例(自动生成 apply 方法,无需 new)
val stu1 = Student(1, "Alice", 20)
val stu2 = Student(2, "Bob", 21)
自动生成的方法
样例类会自动生成以下方法,无需手动实现:
apply方法:允许直接通过类名创建实例(如Student(1, "Alice", 20)),无需new关键字。unapply方法:支持模式匹配(核心特性),可从实例中提取构造参数。toString方法:返回格式化的字符串(如Student(1, Alice, 20)),便于调试。equals和hashCode方法:基于构造参数实现,支持值比较(而非引用比较)。copy方法:用于创建实例的副本,可修改部分参数(适合不可变数据)。
样例类的核心特性详解
不可变的构造参数
样例类的构造参数默认被 val 修饰(不可变),确保实例创建后无法修改:
case class Book(isbn: String, title: String)
val book = Book("978-0134685991", "Scala Programming")
// 编译错误:无法修改 val 变量
// book.title = "New Title"
如需可变参数,可显式声明为 var(但不推荐,违背不可变设计原则):
case class MutableUser(var name: String)
val user = MutableUser("Charlie")
user.name = "David" // 允许修改(不推荐)
模式匹配支持
样例类的 unapply 方法使其天然支持模式匹配,无需手动实现提取器:
// 定义样例类
case class Apple(color: String)
case class Banana(ripeness: String)
case class Orange(weight: Double)
// 水果列表
val fruits: List[Any] = List(
Apple("red"),
Banana("ripe"),
Orange(0.2)
)
// 模式匹配样例类
for (fruit <- fruits) {
fruit match {
case Apple(color) => println(s"苹果,颜色:$color")
case Banana(ripeness) => println(s"香蕉,成熟度:$ripeness")
case Orange(weight) => println(s"橙子,重量:$weight kg")
}
}
输出结果:
苹果,颜色:red
香蕉,成熟度:ripe
橙子,重量:0.2 kg
值比较(而非引用比较)
样例类的 equals 方法基于构造参数实现,两个实例只要参数相同就视为相等:
case class Point(x: Int, y: Int)
val p1 = Point(1, 2)
val p2 = Point(1, 2)
val p3 = Point(3, 4)
println(p1 == p2) // 输出:true(参数相同,值相等)
println(p1 == p3) // 输出:false(参数不同)
普通类默认使用引用比较(需手动重写 equals 和 hashCode),而样例类自动实现了值比较,非常适合作为数据载体。
便捷的复制方法(copy)
样例类的 copy 方法用于创建实例的副本,可选择性修改部分参数(适合不可变数据的更新):
case class Car(brand: String, price: Double)
val car1 = Car("Toyota", 15000.0)
// 复制并修改价格
val car2 = car1.copy(price = 16000.0)
println(car1) // 输出:Car(Toyota, 15000.0)
println(car2) // 输出:Car(Toyota, 16000.0)
copy 方法避免了手动创建新实例时重复输入所有参数,尤其适合参数较多的样例类。
样例对象(Case Object)
样例对象(case object)是单例的样例类,无构造参数,常用于:
- 表示枚举值
- 作为消息传递(如 Akka 中的消息)
// 定义样例对象(单例)
case object Success
case object Failure
// 模式匹配样例对象
def handleResult(result: Any): Unit = result match {
case Success => println("操作成功")
case Failure => println("操作失败")
}
handleResult(Success) // 输出:操作成功
handleResult(Failure) // 输出:操作失败
样例对象自动实现了 toString、equals 等方法,且是单例(Success == Success 始终为 true)。
样例类的适用场景
- 数据建模:适合表示不可变的数据(如 DTO、领域模型),自动生成的方法简化代码。
- 模式匹配:作为模式匹配的载体,无需手动实现
unapply方法。 - 消息传递:在并发编程(如 Akka)中,样例类 / 对象常作为消息传递,支持高效匹配。
- 集合元素:由于支持值比较,适合作为集合元素(如
Set去重、Map键)。
样例类与普通类的对比
| 特性 | 样例类(Case Class) | 普通类(Class) |
|---|---|---|
| 实例创建 | 无需 new(自动生成 apply) |
需要 new 关键字 |
| 构造参数 | 默认 val(不可变) |
默认无修饰符(需显式 val/var) |
| 模式匹配 | 自动支持(生成 unapply) |
需手动实现 unapply 才能支持 |
| 常用方法 | 自动生成 toString/equals/hashCode |
需手动重写 |
| 复制功能 | 自动生成 copy 方法 |
需手动实现 |