Scala 3 新特性实战:enum、given/using、缩进语法与迁移指南

系统讲解 Scala 3(Dotty)新特性:enum 定义、given/using 上下文参数、扩展方法、缩进语法与可选大括号、type 别名与交集/联合类型、Match Types、以及从 Scala 2 迁移到 Scala 3 的实践指南与兼容策略。

引言

Scala 3(代号 Dotty)是 Scala 语言十年磨一剑的重写:语法更简洁、类型系统更强、学习曲线更平缓。它吸收了大量社区反馈,把 Scala 2 的「高级但难学」改造成「高级且好懂」。

本文聚焦 Scala 3 最关键的六块新特性:enum(更简洁的代数数据类型)、given/using(替代 Scala 2 的 implicit,上下文参数更清晰)、扩展方法(不侵入地给类型加方法)、缩进语法(可选大括号的现代化风格)、交集/联合类型与 Match Types(更强的类型表达),最后给出从 Scala 2 迁移的实战指南。

前置:Scala 基础与类型系统(https://plumephp.com/scala-type-system/、https://plumephp.com/scala-functional-programming/)。


目录


1. Scala 3 为什么值得学

1.1 定位

版本特点
Scala 2功能强大但语法繁琐、implicit 难懂
Scala 3语法简洁、类型系统更强、学习曲线平缓

1.2 核心理念

  • 更少的「魔法」:隐式转换大幅收紧,given/using 显式清晰。
  • 更简单的语法:缩进取代大括号。
  • 更强的类型:交集/联合类型、Match Types、opaque types。

2. enum:更简洁的 ADT

2.1 定义

enum Color:
  case Red, Green, Blue

enum PaymentMethod:
  case Card(number: String, exp: String)
  case BankTransfer(account: String)
  case Cash

2.2 用 enum 建模

enum OrderStatus(val label: String):
  case Created extends OrderStatus("已创建")
  case Paid    extends OrderStatus("已支付")
  case Shipped extends OrderStatus("已发货")

val s = OrderStatus.Paid
println(s.label)   // 已支付

2.3 穷尽匹配

def describe(m: PaymentMethod): String = m match {
  case PaymentMethod.Card(n, _)    => s"卡号 $n"
  case PaymentMethod.BankTransfer(_) => "转账"
  case PaymentMethod.Cash          => "现金"
}
// enum + match:编译器穷尽检查

enum 让 ADT 的定义和用例都大幅简化,是 Scala 3 最受欢迎的新特性之一。


3. given/using:上下文参数新范式

3.1 替代 implicit

Scala 2 的 implicit 承担了「自动传参 + 隐式转换 + 隐式类」多种职责,易混淆。Scala 3 拆成 given(提供实例)与 using(消费实例)。

3.2 基础用法

// 提供实例
given intOrd: Ordering[Int] with {
  def compare(a: Int, b: Int): Int = a.compare(b)
}

// 消费实例
def maxOf[A](list: List[A])(using ord: Ordering[A]): A = list.max

maxOf(List(1, 3, 2))   // 自动找到 given intOrd → 3

3.3 语法糖:上下文绑定

// 等价写法:上下文绑定
def maxOf[A: Ordering](list: List[A]): A = list.max

3.4 与 Scala 2 对照

Scala 2Scala 3
implicit valgiven
implicit defgiven ... with
隐式参数 (implicit x: T)(using x: T)
上下文绑定 [A: T]相同

4. 扩展方法:无侵入地加行为

4.1 给已有类型加方法

extension (n: Int)
  def squared: Int = n * n
  def isEven: Boolean = n % 2 == 0

println(4.squared)   // 16
println(3.isEven)    // false

4.2 泛型扩展

extension [A](list: List[A])
  def second: Option[A] = list.drop(1).headOption

List(1, 2, 3).second    // Some(2)
List(1).second          // None

4.3 与隐式类的对比

Scala 2 用 implicit class,Scala 3 用 extension——更清晰,不易误用。


5. 缩进语法:现代化书写风格

5.1 大括号可省略

// Scala 2 风格
def add(a: Int, b: Int): Int = {
  val sum = a + b
  sum
}

// Scala 3 缩进风格
def add(a: Int, b: Int): Int =
  val sum = a + b
  sum

5.2 条件与循环

val result =
  if x > 0 then "正"
  else "非正"

for i <- 1 to 3 do
  println(i)

5.3 混用注意

  • 同一段代码不要混用大括号与缩进。
  • 缩进是两空格(或与配置一致)。
  • IDE(IntelliJ/VSCode)有自动格式化。

6. 交集、联合类型与 Match Types

6.1 联合类型

def handle(x: Int | String): String = x match {
  case i: Int    => s"整数 $i"
  case s: String => s"字符串 $s"
}

handle(42)          // 整数 42
handle("hello")     // 字符串 hello

6.2 交集类型

trait Readable { def read(): String }
trait Writable { def write(s: String): Unit }

def io(device: Readable & Writable): Unit = {
  val data = device.read()
  device.write(data)
}

6.3 Match Types:类型层面的分支

type Elem[X] = X match {
  case String      => Char
  case Array[t]    => t
  case List[t]     => t
}

val c: Elem[String] = 'a'          // Char
val i: Elem[List[Int]] = 1         // Int

Match Types 让类型系统具备「计算能力」,是 Scala 3 的杀手锏之一。


7. 其他值得关注的新特性

特性说明
opaque types隐藏底层类型,防误用
可选参数名(命名实参)提升可读性
更好的推导类型推导更聪明
工具库(**、! 非)语法糖
跨版本兼容-Xsource:3 迁移模式
// opaque types 示例
opaque type UserId = Long
object UserId:
  def apply(id: Long): UserId = id
  extension (id: UserId) def value: Long = id

val uid = UserId(42)
// uid + 1   // ❌ 编译错误,UserId 是独立类型,防误用

8. 从 Scala 2 迁移到 Scala 3

8.1 迁移步骤

# 1. 确认依赖兼容(用 scala-2.13 迁移检查)
# 2. 项目切到 Scala 3.3(LTS)
# 3. 逐个模块编译,修 implicit 相关错误
# 4. 启用 -Xsource:3 渐进迁移

8.2 常见迁移点

Scala 2Scala 3
implicit val xgiven x: T
implicit defgiven ... with
implicit classextension
view bounds已移除(改用 given)
符号 => 语法=>(旧符号移除)

8.3 兼容性策略

  • Scala 3 可编译 Scala 2.13 写的库(跨版本互操作)。
  • 大型项目可分模块渐进迁移。
  • 生态大部分库已提供 Scala 3 版本(sbt 里 scalaVersion := "3.3.x")。
// build.sbt
scalaVersion := "3.3.4"

9. 总结:Scala 3 学习路线图

9.1 优先学什么

优先级特性收益
高enumADT 建模更简单
高given/using告别 implicit 迷雾
高extension优雅扩展
中缩进语法代码更清爽
中Match Types类型层计算
低opaque types高级防御

9.2 一句话心法

Scala 3 = 更简洁的语法 + 更清晰的上下文 + 更强的类型。它让「学习 Scala 的陡峭曲线」明显变缓,是入手函数式 + 类型安全编程的更好起点。


延伸阅读

  • https://plumephp.com/scala-type-system/ — 类型类与 given/using 的底层
  • https://plumephp.com/scala-functional-programming/ — 函数式范式在 Scala 3 中的呈现
  • Scala 3 官方文档 与 迁移指南

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「scala」更多文章

  1. 纯函数式效果系统实战:Cats Effect IO 与 ZIO
  2. Scala.js 与 Scala Native:跨平台编译、互操作与工程实践
  3. Scala 领域建模实战:ADT、类型驱动设计与模块化架构