You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现行为一致但不可混用的Scala opaque类型别名?

问题解决:实现同底层但不可混用的强类型

你希望创建两个基于同一底层类型的类型,它们拥有相同的行为但完全不可混用(类似米和秒不能相加,但同类型可以相加并返回对应类型),但当前使用opaque类型的实现没有达到预期:同类型相加返回底层类型,不同类型还能直接相加。

问题原因分析

你原来的代码中,opaque type myType1 <: foo = foo让myType1成为foo的子类型,这意味着:

  • 调用foo类的+方法时,myType1和myType2都会被自动向上转型为foo,所以不同类型可以互相传入
  • +方法返回的是foo类型,而非对应的opaque类型

正确实现方案

我们需要让opaque类型不继承foo,而是将Double作为底层类型,然后为每个opaque类型单独定义扩展方法来实现加法逻辑,这样就能保证类型隔离:

object example {
  // 直接基于Double定义opaque类型,不依赖中间类
  opaque type myType1 = Double
  opaque type myType2 = Double

  // 为myType1实现转换与加法
  extension (d: Double)
    def toMyType1: myType1 = d
  extension (mt1: myType1)
    def +(that: myType1): myType1 = mt1 + that
    // 可选:提供获取底层值的方法
    def value: Double = mt1

  // 为myType2实现相同逻辑的方法
  extension (d: Double)
    def toMyType2: myType2 = d
  extension (mt2: myType2)
    def +(that: myType2): myType2 = mt2 + that
    def value: Double = mt2
}

import example.{myType1, myType2}
import example.{toMyType1, toMyType2, given}

val a1 = 1.5.toMyType1 // a1: myType1
val a2 = 2.4.toMyType1 // a2: myType1
val b1 = 3.2.toMyType2 // b1: myType2

val a3 = a1 + a2       // a3: myType1 ✅ 符合预期
// val c1 = a1 + b1     // 编译错误 ✅ 符合预期:类型不匹配,无法将myType2传入myType1的+方法

如果需要复用加法逻辑避免重复代码,可以提取通用工具方法:

object example {
  opaque type myType1 = Double
  opaque type myType2 = Double

  // 通用加法逻辑,通过类型约束复用代码
  private def add[T](a: T, b: T)(using ev: T =:= Double): T = ev(a) + ev(b)

  extension (d: Double)
    def toMyType1: myType1 = d
    def toMyType2: myType2 = d

  extension (mt1: myType1)
    def +(that: myType1): myType1 = add(mt1, that)
    def value: Double = mt1

  extension (mt2: myType2)
    def +(that: myType2): myType2 = add(mt2, that)
    def value: Double = mt2
}

效果验证

  • 同类型相加返回对应opaque类型,符合预期
  • 不同类型相加直接触发编译错误,实现了严格的类型隔离
  • 底层类型均为Double,无额外性能开销,契合opaque类型的设计初衷

内容的提问来源于stack exchange,提问作者t9dupuy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 19:33:16