1. 概述

现代面向对象编程语言通常会提供一些抽象机制来表示简单、不可变的数据结构。在 Scala 中,这种机制就是 case class(样例类)

本文将深入探讨 Scala 中的 case class,对比它与普通 class 的差异,并分析它所带来的优势。

2. Case Class

我们先从一个简单的 case class 定义开始:

case class CovidCountryStats(countryCode: String, deaths: Int, confirmedCases: Int)

✅ 默认情况下,所有构造参数都是 公共且不可变的(val)。虽然你可以将它们声明为 var,但这并不是 case class 的设计初衷。

⚠️ 注意,这与普通 class 的默认行为不同 —— 普通 class 的构造参数默认是私有的。

Scala 的 case class 在设计上与 Kotlin 的 data class 非常相似,Java 14 引入的 records 也有异曲同工之妙。

接下来,我们来看看 case class 提供的几大特性。

2.1. 简洁的实例化语法

创建 case class 实例非常简洁:

val covidPL = CovidCountryStats("PL", 776, 15366)

注意,我们没有使用 new 关键字。这是因为 case class 会自动生成一个 apply 方法,由编译器自动提供。

如果 case class 嵌套使用,这种简洁语法也能让复杂对象的创建变得非常直观!

2.2. 模式匹配支持

case class 最强大的特性之一就是支持模式匹配(Pattern Matching),可以优雅地解构对象:

covidPL match {
    case CovidCountryStats("PL", x, y) => println("Death rate for Poland is " + x.toFloat / y.toFloat)
    ...
    case _ => println("Unknown country")
}

这之所以可行,是因为 case class 会自动生成一个伴生对象(companion object),其中包含:

  • apply 方法(用于实例化)
  • unapply 方法(用于提取器,支持模式匹配)

2.3. 自动生成的方法

和 Kotlin 的 data class 一样,Scala 的 case class 会自动实现以下方法:

  • equals
  • hashCode
  • toString

并且这些方法都是基于字段内容自动生成的,非常实用。

2.4. 结构相等性

case class 实例默认是 结构相等 的,而不是引用相等:

assert(CovidCountryStats("PL", 776, 15366) == CovidCountryStats("PL", 776, 15366))

✅ 上述断言会通过,因为两个对象的内容完全一致。

❌ 如果去掉 case 关键字,变成普通 class,默认的 == 是基于引用的,结果会是 false

2.5. Product 特质

case class 默认继承了 Product 特质,因此具备以下方法:

  • productElement(n: Int): Any:获取第 n 个参数
  • productArity: Int:获取参数个数
  • productIterator: Iterator[Any]:迭代所有参数

⚠️ 由于 Product 的限制,case class 最多只能有 22 个参数

2.6. 浅拷贝的 copy 方法

case class 自动提供 copy 方法,用于创建新的实例(浅拷贝):

val covidUA = covidPL.copy(countryCode = "UA")

⚠️ 注意:copy 只做浅拷贝,嵌套对象不会被深拷贝。

2.7. tupled 方法

case class 的伴生对象还提供了一个 tupled 方法,可以从元组创建对象:

val tuple = ("PL", 776, 15366)
val covidPL = (CovidCountryStats.apply _).tupled(tuple)

这个特性在函数式编程中尤其有用。

2.8. 其他注意事项

在使用 case class 时还需注意以下限制:

  • ❌ case class 不能继承另一个 case class
  • ✅ case class 默认实现了 Serializable 接口

3. 总结

在这篇文章中,我们详细介绍了 Scala 中的 case class,对比了它与普通 class 的区别。

case class 的优势在于:

  • ✅ 极大地减少了样板代码
  • ✅ 支持模式匹配
  • ✅ 自动生成常用方法(equals、hashCode、toString)
  • ✅ 结构相等性
  • ✅ 支持 copy 和 tupled 等实用方法

⚠️ 但也要注意,这些便利的背后是编译器自动生成的约 20 个方法,可能会略微增加字节码体积。

💡 最后,推荐使用 scalac -print 命令查看 case class 编译后的实际代码,有助于深入理解其底层机制。

如需获取文中代码示例,可访问:GitHub 仓库


原始标题:Difference Between Class and Case Class in Scala

» 下一篇: Scala 泛型基础