类型类派生
自动生成实例
类型类派生 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
什么是派生?
类型类派生会根据类型的结构自动生成实例,因此您无需为每个样例类手写重复代码。编译器会根据类型的字段构建实例。
重复样板代码的问题
没有派生功能时,每个新的样例类都需要手动创建实例。如果要为二十个样例类实现 Show,就需要编写二十个几乎完全相同的定义。派生功能消除了这种重复。
先手动组合
在学习自动派生之前,请先注意:您可以根据各字段的实例手动组合出新的实例。这正是派生功能要自动完成的原则。
trait Show[A] { def show(a: A): String }
case class User(name: String, age: Int)
object Main {
implicit val strShow: Show[String] = s => s
implicit val intShow: Show[Int] = _.toString
implicit val userShow: Show[User] = (u: User) =>
s"User(${strShow.show(u.name)}, ${intShow.show(u.age)})"
def main(args: Array[String]): Unit = {
println(userShow.show(User("Ann", 30)))
}
}归纳式实例
派生以归纳方式工作:先为基本类型定义实例,然后为积类型(样例类)和和类型(密封特征)组合这些实例。派生实例由各个组成部分构建而成。
Scala 3 的 derives 关键字
Scala 3 支持 derives 子句。带有 derived 方法的类型类,可以通过一个关键字附加到某个类型上。(概念性代码片段;需要可派生的类型类。)
enum Color derives CanEqual:
case Red, Green, Blue
@main def run(): Unit =
println(Color.Red == Color.Red)基于 Mirror 的派生
Scala 3 的派生机制使用 scala.deriving.Mirror,在编译时公开类型的结构(字段类型和名称)。derived 方法会遍历镜像中的元素实例,从而构建出整体实例。
半自动派生
Cats 等库提供半自动派生:您可以针对每个类型,通过 deriveShow 这样的一行代码选择启用,在消除样板代码的同时,让编译时间保持可预测。
自动派生与半自动派生
两种方式:
- 自动:通过隐式导入,在需要的地方自动生成实例;使用方便,但可能拖慢编译速度。
- 半自动:您为每个类型显式编写一次派生调用;控制力更强,构建速度更快。
密封特征的派生
对于密封层次结构(即和类型),派生实例会根据值所属的子类型进行分派。下面的手动版本展示了派生机制所自动完成的思路。
trait Show[A] { def show(a: A): String }
sealed trait Shape
case class Circle(r: Int) extends Shape
case class Square(s: Int) extends Shape
object Main {
implicit val shapeShow: Show[Shape] = {
case Circle(r) => s"Circle($r)"
case Square(s) => s"Square($s)"
}
def main(args: Array[String]): Unit = {
println(shapeShow.show(Circle(5)))
println(shapeShow.show(Square(3)))
}
}何时使用派生
在以下情况下可以使用派生:
- 您有许多数据类型需要同一个类型类(JSON 编解码器、Show、Eq)。
- 该实例可以根据结构机械地生成。
当行为是定制的,或对性能要求很高时,请手动编写实例。
通用相等性示例
相等性是一个经典的可派生类型类。标准的案例类 == 本身就是一种结构相等性,由编译器为您生成。
case class Coord(x: Int, y: Int)
object Main {
def main(args: Array[String]): Unit = {
println(Coord(1, 2) == Coord(1, 2))
println(Coord(1, 2) == Coord(3, 4))
}
}快速检查
检验您对派生机制的理解。
回顾
您学习了类型类派生:
- 实例通过字段实例或案例实例逐步构建。
- Scala 3 使用
Mirror和derives关键字。 - 为方便起见选择自动派生,为了控制力选择半自动派生。
- 使用它可以消除许多数据类型中的样板代码。
常见问题解答
「类型类派生」课时是免费的吗?
是的 — 「类型类派生」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
「类型类派生」这节课中我会学到什么?
自动生成实例 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「类型类派生」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?
能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。