0%

scala样例类

Scala 样例类(Case Class):模式匹配的完美搭档

样例类(Case Class)是 Scala 中一种特殊的类,专门为模式匹配不可变数据建模设计。它自动生成了一系列常用方法,大幅简化了数据封装和匹配的代码。本文将详细解析样例类的特性、用法及适用场景。

样例类的定义与基本特性

样例类通过 case class 关键字定义,与普通类相比,它具有以下默认特性:

1
2
3
4
5
6
// 定义样例类(无需 new 关键字即可创建实例)
case class Student(id: Int, name: String, age: Int)

// 创建实例(自动生成 apply 方法,无需 new)
val stu1 = Student(1, "Alice", 20)
val stu2 = Student(2, "Bob", 21)

自动生成的方法

样例类会自动生成以下方法,无需手动实现:

  1. apply 方法:允许直接通过类名创建实例(如 Student(1, "Alice", 20)),无需 new 关键字。
  2. unapply 方法:支持模式匹配(核心特性),可从实例中提取构造参数。
  3. toString 方法:返回格式化的字符串(如 Student(1, Alice, 20)),便于调试。
  4. equalshashCode 方法:基于构造参数实现,支持值比较(而非引用比较)。
  5. copy 方法:用于创建实例的副本,可修改部分参数(适合不可变数据)。

样例类的核心特性详解

不可变的构造参数

样例类的构造参数默认被 val 修饰(不可变),确保实例创建后无法修改:

1
2
3
4
5
6
case class Book(isbn: String, title: String)

val book = Book("978-0134685991", "Scala Programming")

// 编译错误:无法修改 val 变量
// book.title = "New Title"

如需可变参数,可显式声明为 var(但不推荐,违背不可变设计原则):

1
2
3
case class MutableUser(var name: String)
val user = MutableUser("Charlie")
user.name = "David" // 允许修改(不推荐)

模式匹配支持

样例类的 unapply 方法使其天然支持模式匹配,无需手动实现提取器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 定义样例类
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")
}
}

输出结果

1
2
3
苹果,颜色:red
香蕉,成熟度:ripe
橙子,重量:0.2 kg

值比较(而非引用比较)

样例类的 equals 方法基于构造参数实现,两个实例只要参数相同就视为相等:

1
2
3
4
5
6
7
8
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(参数不同)

普通类默认使用引用比较(需手动重写 equalshashCode),而样例类自动实现了值比较,非常适合作为数据载体。

便捷的复制方法(copy

样例类的 copy 方法用于创建实例的副本,可选择性修改部分参数(适合不可变数据的更新):

1
2
3
4
5
6
7
8
9
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 中的消息)
1
2
3
4
5
6
7
8
9
10
11
12
// 定义样例对象(单例)
case object Success
case object Failure

// 模式匹配样例对象
def handleResult(result: Any): Unit = result match {
case Success => println("操作成功")
case Failure => println("操作失败")
}

handleResult(Success) // 输出:操作成功
handleResult(Failure) // 输出:操作失败

样例对象自动实现了 toStringequals 等方法,且是单例(Success == Success 始终为 true)。

样例类的适用场景

  1. 数据建模:适合表示不可变的数据(如 DTO、领域模型),自动生成的方法简化代码。
  2. 模式匹配:作为模式匹配的载体,无需手动实现 unapply 方法。
  3. 消息传递:在并发编程(如 Akka)中,样例类 / 对象常作为消息传递,支持高效匹配。
  4. 集合元素:由于支持值比较,适合作为集合元素(如 Set 去重、Map 键)。

样例类与普通类的对比

特性 样例类(Case Class) 普通类(Class)
实例创建 无需 new(自动生成 apply 需要 new 关键字
构造参数 默认 val(不可变) 默认无修饰符(需显式 val/var
模式匹配 自动支持(生成 unapply 需手动实现 unapply 才能支持
常用方法 自动生成 toString/equals/hashCode 需手动重写
复制功能 自动生成 copy 方法 需手动实现

欢迎关注我的其它发布渠道