Skip to content

子类型

Subtyping

允许某类型值在期望其上界类型的位置使用的可替代关系。

条目类型
定义

形式陈述

子类型关系 S<:T 表示每个 S 型值都可在期望 T 型值的位置安全使用。类型系统通常包含自反性、传递性和 subsumption 规则

Γt:SS<:TΓt:T.

因此子类型通常首先是预序,而非语法类型上的偏序:互为子类型的两个类型未必字面相同;按 STS<:TT<:S 取商后,才可把等价类视为反对称的偏序。

函数类型满足参数逆变、结果协变:

S2<:S1T1<:T2S1T1<:S2T2.

不可变积与记录通常按分量协变;记录还可有宽度子类型。含可写位置的引用类型一般不能简单协变,否则会破坏类型安全。

直觉

子类型不是“结构看起来像”或“类继承了谁”,而是上下文中的可替代性承诺。函数参数逆变最容易反直觉:一个能处理所有动物的函数当然能放到只会收到猫的位置,而只处理猫的函数不能冒充能处理所有动物的函数。结果则相反,返回更具体的猫可安全当作返回动物。定义中的方向由谁提供、谁消费数据决定,而不是由语法箭头机械决定。

例子与边界

结构记录中,若只读字段采用宽度子类型,则 {x:Int,y:Int}<:{x:Int}:需要 x 的代码可以忽略额外的 y。函数 Animal→Cat 可作为 Cat→Animal 使用,因为它接受范围更广、返回结果更具体。

边界是可变引用。若假设 Ref Cat <: Ref Animal,代码可通过 Ref Animal 写入一只狗,原持有者随后从 Ref Cat 读出狗,类型承诺被破坏;因此可读写引用通常不变。名义继承也不自动等于行为子类型,违反方法契约的子类不能仅凭语法继承获得可靠替代性。

推论与应用

子类型支撑面向对象接口、记录扩展、数值层次和 API 演化。所有权与借用还会把生命周期包含解释成引用可缩短使用区间的 region subtyping;独占 reborrow 与可变引用的 variance 另有别名约束,不能从普通协变机械推出。算法类型检查需要决定 S<:T,复杂系统还需处理交、并、递归类型与有界量化。

它与参数多态是不同复用机制:前者允许较具体值向上转换,后者要求同一代码对所有类型参数统一工作。类型判断通过 subsumption 接纳子类型,而类型安全约束每条子类型规则必须保持运行时行为。

参考资料
  • Benjamin C. Pierce, Types and Programming Languages, MIT Press, 2002,Chs. 15–18, subtyping, records, and variants。
  • Robert Harper, Practical Foundations for Programming Languages, 2nd ed., Cambridge University Press, 2016,Chs. 21–24, subtyping and variance。
关系图谱7 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系

并列辨析