样例类 #
一、样例类基础 #
1.1 定义样例类 #
使用 case class 关键字:
scala
case class Person(name: String, age: Int)
val person = Person("Alice", 25)
println(person.name)
println(person.age)
1.2 自动生成的特性 #
case class 自动生成:
apply方法(无需 new)toString方法equals和hashCode方法copy方法unapply方法(模式匹配)
1.3 与普通类对比 #
scala
class Person1(val name: String, val age: Int)
case class Person2(name: String, age: Int)
val p1 = Person1("Alice", 25)
val p2 = Person2("Alice", 25)
println(p1)
println(p2)
二、样例类特性 #
2.1 自动生成 apply #
scala
case class Person(name: String, age: Int)
val person = Person("Alice", 25)
2.2 自动生成 toString #
scala
case class Person(name: String, age: Int)
val person = Person("Alice", 25)
println(person)
2.3 自动生成 equals 和 hashCode #
scala
case class Person(name: String, age: Int)
val p1 = Person("Alice", 25)
val p2 = Person("Alice", 25)
val p3 = Person("Bob", 30)
println(p1 == p2)
println(p1 == p3)
val set = Set(p1, p2, p3)
println(set.size)
2.4 copy 方法 #
scala
case class Person(name: String, age: Int)
val p1 = Person("Alice", 25)
val p2 = p1.copy(age = 26)
val p3 = p1.copy(name = "Bob")
println(p1)
println(p2)
println(p3)
2.5 模式匹配 #
scala
case class Person(name: String, age: Int)
def describe(person: Person): String = person match
case Person("Alice", _) => "It's Alice"
case Person(name, age) if age < 18 => s"$name is a minor"
case Person(name, age) => s"$name is $age years old"
println(describe(Person("Alice", 25)))
println(describe(Person("Bob", 15)))
println(describe(Person("Charlie", 30)))
三、不可变性 #
3.1 默认不可变 #
case class 的参数默认是 val:
scala
case class Person(name: String, age: Int)
val person = Person("Alice", 25)
3.2 使用 copy 修改 #
scala
case class Person(name: String, age: Int)
val p1 = Person("Alice", 25)
val p2 = p1.copy(age = 26)
3.3 可变字段(不推荐) #
scala
case class Counter(var count: Int)
val counter = Counter(0)
counter.count += 1
println(counter.count)
四、模式匹配详解 #
4.1 基本匹配 #
scala
case class Point(x: Int, y: Int)
val point = Point(10, 20)
val result = point match
case Point(0, 0) => "Origin"
case Point(x, 0) => s"On x-axis at $x"
case Point(0, y) => s"On y-axis at $y"
case Point(x, y) => s"Point at ($x, $y)"
println(result)
4.2 守卫条件 #
scala
case class Person(name: String, age: Int)
def categorize(person: Person): String = person match
case Person(_, age) if age < 0 => "Invalid age"
case Person(_, age) if age < 13 => "Child"
case Person(_, age) if age < 20 => "Teenager"
case Person(_, age) if age < 65 => "Adult"
case _ => "Senior"
4.3 嵌套匹配 #
scala
case class Address(city: String, country: String)
case class Person(name: String, address: Address)
val person = Person("Alice", Address("Beijing", "China"))
val result = person match
case Person(name, Address("Beijing", _)) => s"$name lives in Beijing"
case Person(name, Address(_, "China")) => s"$name lives in China"
case Person(name, _) => s"$name lives somewhere"
4.4 集合中的模式匹配 #
scala
case class Person(name: String, age: Int)
val people = List(
Person("Alice", 25),
Person("Bob", 17),
Person("Charlie", 30)
)
val adults = people.collect {
case p @ Person(_, age) if age >= 18 => p
}
val names = people.map { case Person(name, _) => name }
五、样例对象 #
5.1 定义样例对象 #
scala
case object Empty
case class NonEmpty(head: Int, tail: List[Int])
def describe(list: List[Int]): String = list match
case Nil => Empty.toString
case head :: tail => NonEmpty(head, tail).toString
5.2 作为消息 #
scala
sealed trait Message
case object Start extends Message
case object Stop extends Message
case class Data(value: Int) extends Message
def handle(message: Message): String = message match
case Start => "Starting..."
case Stop => "Stopping..."
case Data(value) => s"Received data: $value"
5.3 作为枚举替代 #
scala
sealed trait Direction
case object North extends Direction
case object South extends Direction
case object East extends Direction
case object West extends Direction
def turn(direction: Direction): String = direction match
case North => "Going North"
case South => "Going South"
case East => "Going East"
case West => "Going West"
六、Sealed 特质与样例类 #
6.1 定义 Sealed 层次 #
scala
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
case class Triangle(a: Double, b: Double, c: Double) extends Shape
6.2 穷尽性检查 #
scala
def area(shape: Shape): Double = shape match
case Circle(r) => math.Pi * r * r
case Rectangle(w, h) => w * h
case Triangle(a, b, c) =>
val s = (a + b + c) / 2
math.sqrt(s * (s - a) * (s - b) * (s - c))
6.3 实用示例 #
scala
sealed trait Result[+T]
case class Success[T](value: T) extends Result[T]
case class Failure(message: String) extends Result[Nothing]
def divide(a: Int, b: Int): Result[Int] =
if b == 0 then Failure("Division by zero")
else Success(a / b)
def handle(result: Result[Int]): String = result match
case Success(value) => s"Result: $value"
case Failure(msg) => s"Error: $msg"
七、实战示例 #
7.1 表达式求值器 #
scala
sealed trait Expr
case class Number(value: Int) extends Expr
case class Add(left: Expr, right: Expr) extends Expr
case class Subtract(left: Expr, right: Expr) extends Expr
case class Multiply(left: Expr, right: Expr) extends Expr
def evaluate(expr: Expr): Int = expr match
case Number(v) => v
case Add(l, r) => evaluate(l) + evaluate(r)
case Subtract(l, r) => evaluate(l) - evaluate(r)
case Multiply(l, r) => evaluate(l) * evaluate(r)
val expr = Add(Number(1), Multiply(Number(2), Number(3)))
println(evaluate(expr))
7.2 JSON 解析 #
scala
sealed trait Json
case class JsonString(value: String) extends Json
case class JsonNumber(value: Double) extends Json
case class JsonBoolean(value: Boolean) extends Json
case class JsonArray(values: List[Json]) extends Json
case class JsonObject(fields: Map[String, Json]) extends Json
case object JsonNull extends Json
def stringify(json: Json): String = json match
case JsonString(s) => s""""$s""""
case JsonNumber(n) => n.toString
case JsonBoolean(b) => b.toString
case JsonArray(arr) => arr.map(stringify).mkString("[", ", ", "]")
case JsonObject(obj) => obj.map { case (k, v) => s""""$k": ${stringify(v)}""" }
.mkString("{", ", ", "}")
case JsonNull => "null"
7.3 状态机 #
scala
sealed trait State
case object Idle extends State
case class Processing(progress: Int) extends State
case class Completed(result: String) extends State
case class Failed(error: String) extends State
def transition(current: State, event: String): State = (current, event) match
case (Idle, "start") => Processing(0)
case (Processing(p), "progress") if p < 100 => Processing(p + 10)
case (Processing(100), "complete") => Completed("Done")
case (Processing(_), "fail") => Failed("Error occurred")
case (Completed(_) | Failed(_), "reset") => Idle
case _ => current
八、样例类最佳实践 #
8.1 用于数据建模 #
scala
case class User(
id: Long,
name: String,
email: String,
createdAt: java.time.Instant
)
8.2 与 Sealed 结合 #
scala
sealed trait PaymentMethod
case class CreditCard(number: String, expiry: String) extends PaymentMethod
case class BankAccount(accountNumber: String, routingNumber: String) extends PaymentMethod
case object Cash extends PaymentMethod
8.3 保持不可变 #
scala
case class Counter(value: Int):
def increment: Counter = copy(value = value + 1)
def decrement: Counter = copy(value = value - 1)
val c1 = Counter(0)
val c2 = c1.increment
val c3 = c2.increment
九、总结 #
case class 自动生成 #
| 方法 | 说明 |
|---|---|
| apply | 无需 new 创建实例 |
| toString | 格式化输出 |
| equals | 值比较 |
| hashCode | 哈希计算 |
| copy | 复制修改 |
| unapply | 模式匹配 |
使用场景 #
| 场景 | 说明 |
|---|---|
| 数据模型 | 表示数据实体 |
| 消息传递 | Actor 消息 |
| 模式匹配 | 结构化匹配 |
| 不可变数据 | 函数式编程 |
下一步,让我们学习 对象与伴生对象!
最后更新:2026-03-27