如何为Scala枚举值的子集定义函数?实现编译期参数约束
解决方案
你原来用Enumeration实现的枚举无法在编译期区分A1/A2/A3,因为它们本质都是Int类型,编译器没法识别出三者的类型差异。要实现调用foo(A.A3)时触发编译错误,需要改用密封特质(sealed trait)+ case object的枚举实现方式,让每个枚举成员拥有独立的类型。
Scala 3 实现(支持联合类型)
首先重新定义枚举结构:
sealed trait A case object A1 extends A case object A2 extends A case object A3 extends A
然后定义foo函数,直接用联合类型限定参数只能是A1或A2:
def foo(a: A1 | A2): Int = a match { case A1 => 1 // 业务逻辑 case A2 => 2 // 业务逻辑 }
此时调用foo(A3)会直接触发编译错误,完全符合你的需求。
Scala 2 实现(不支持联合类型)
如果使用Scala 2,可通过新增一个子特质来限定允许的枚举成员:
sealed trait A trait AllowedA extends A // 仅允许A1、A2继承此特质 case object A1 extends AllowedA case object A2 extends AllowedA case object A3 extends A def foo(a: AllowedA): Int = a match { case A1 => 1 case A2 => 2 }
这种方式下,A3不属于AllowedA类型,传入foo会直接编译失败。
为什么原Enumeration方案不可行?
你最初的Enumeration定义中,A1/A2/A3都是Int类型(你显式指定了type A = Int),编译器无法在编译阶段区分这三个值的类型,只能在运行时通过匹配抛出异常,无法实现编译期检查。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

