联合类型与交集类型
全新的类型特性
联合类型与交集类型 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
新的类型特性
Scala 3 为类型系统加入了联合类型(A | B)和交集类型(A & B)。它们可以在不依赖继承层次结构的情况下,更精确地描述值。
object Main:
def main(args: Array[String]): Unit =
println("Union: A | B, Intersection: A & B")联合类型基础
联合类型 A | B 表示一个值要么是 A,要么是 B。它是类型之间的集合论 OR。
object Main:
def show(x: Int | String): String = x match
case i: Int => s"int $i"
case s: String => s"str $s"
def main(args: Array[String]): Unit =
println(show(42))
println(show("hi"))联合类型不需要公共超类型
与 Scala 2 的 Either 不同,联合类型不需要包装。任意两个类型都可以组成联合类型,即使它们没有共同的父类。
object Main:
def parse(input: Int | Boolean): String =
input match
case n: Int => s"number $n"
case b: Boolean => s"flag $b"
def main(args: Array[String]): Unit =
println(parse(7))
println(parse(true))使用联合类型建模错误
联合类型适合在不引入包装类型的情况下表示轻量级错误结果。与枚举或单例结合使用时,代码表达清晰。
case object NotFound
object Main:
def lookup(id: Int): String | NotFound.type =
if id == 1 then "Alice" else NotFound
def main(args: Array[String]): Unit =
println(lookup(1))
println(lookup(2))交集类型基础
交集类型 A & B 表示一个值同时是 A 和 B。它是集合论中的 AND,常用于组合特征。
trait Named:
def name: String
trait Aged:
def age: Int
object Main:
def describe(p: Named & Aged): String =
s"${p.name} is ${p.age}"
def main(args: Array[String]): Unit =
val person = new Named with Aged:
def name = "Bob"
def age = 40
println(describe(person))交集满足交换律
交集类型的顺序无关紧要:A & B 与 B & A 是同一个类型。这不同于 Scala 2 的复合类型 A with B,后者在解析某些成员时会受到顺序影响。
trait Readable:
def read: String
trait Writable:
def write(s: String): Unit
object Main:
def use(r: Readable & Writable): Unit =
r.write("x")
println(r.read)
def main(args: Array[String]): Unit =
val rw = new Readable with Writable:
def read = "data"
def write(s: String) = println(s"wrote $s")
use(rw)组合多个特征
您可以对两个以上的类型求交集。结果必须具备列出的全部能力。
trait A: def a: Int
trait B: def b: Int
trait C: def c: Int
object Main:
def sum(x: A & B & C): Int = x.a + x.b + x.c
def main(args: Array[String]): Unit =
val v = new A with B with C:
def a = 1
def b = 2
def c = 3
println(sum(v))联合类型的类型别名
较长的联合类型可以通过 type 别名命名,从而保持签名的可读性。
type Json = Int | String | Boolean
object Main:
def render(j: Json): String = j match
case i: Int => i.toString
case s: String => s"\"$s\""
case b: Boolean => b.toString
def main(args: Array[String]): Unit =
println(render("hi"))
println(render(true))对联合类型进行穷尽匹配
编译器知道联合类型包含哪些成员,因此可以检查匹配是否完整。处理每个可能的分支,就能使匹配覆盖所有情况。
type Shape = "circle" | "square"
object Main:
def sides(s: Shape): Int = s match
case "circle" => 0
case "square" => 4
def main(args: Array[String]): Unit =
println(sides("square"))联合类型的拓宽
将联合类型的值赋给类型推断变量时,Scala 会保留联合类型。请注意,某些操作会将类型拓宽为最小上界;如果希望保留联合类型,请添加类型注解。
object Main:
def pick(flag: Boolean): Int | String =
if flag then 1 else "one"
def main(args: Array[String]): Unit =
val x: Int | String = pick(false)
println(x)何时使用哪一种
请选择合适的工具。
- 联合类型:一个值属于多个类型中的一种(OR)。
- 交集类型:一个值同时满足多个特征(AND)。
- 联合类型避免使用包装类型;交集类型避免构建深层继承结构。
trait Logger: def log(s: String): Unit
trait Clock: def now: Long
object Main:
def run(env: Logger & Clock): Unit =
env.log(s"time=${env.now}")
def main(args: Array[String]): Unit =
val env = new Logger with Clock:
def log(s: String) = println(s)
def now = 100L
run(env)快速检查
测试您对联合类型和交集类型的理解。
回顾
您学习了 Scala 3 的联合类型和交集类型。
A | B:值是 A 或 B,不需要包装器或公共父类型。A & B:值同时是 A 和 B,并且满足交换律。- 使用模式匹配缩小联合类型;使用交集类型组合特征。
- 使用
type别名为较长的联合类型命名。
object Main:
def length(x: String | List[Int]): Int = x match
case s: String => s.length
case l: List[Int] => l.length
def main(args: Array[String]): Unit =
println(length("hello"))
println(length(List(1, 2, 3)))常见问题解答
「联合类型与交集类型」课时是免费的吗?
是的 — 「联合类型与交集类型」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 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 反馈 — 无需本地设置。
此课程中的所有课时
- 显著缩进
- Scala 3 中的枚举
- 不透明类型
- 联合类型与交集类型