如何在Scala 3中对enum类型实现模式匹配
解决方案
Scala 3的枚举类型分两种匹配场景,对应不同的安全实现方式:
场景1:匹配枚举实例
Scala 3中所有枚举实例默认实现了scala.reflect.Enum公共特质,直接按该类型匹配即可,无编译告警、无运行时额外开销:
obj match { case e: scala.reflect.Enum => // 枚举实例的处理逻辑 case other => // 其他类型的处理逻辑 }
场景2:匹配枚举伴生对象(调用values拿所有枚举值)
你之前使用的结构类型{ def values: Array[?] }依赖运行时反射访问,不仅会触发编译告警,scaladoc生成阶段的反射检查还会抛出你遇到的InvocationTargetException异常,推荐使用两种安全替代方案:
方案A:运行时轻量检测
直接通过类名和父类特征判断,避免结构类型语法:
extension (obj: AnyRef) private def isEnumCompanion: Boolean = val cls = obj.getClass // 伴生类名以$结尾,对应的普通类是Enum的子类 cls.getName.endsWith("$") && classOf[scala.reflect.Enum].isAssignableFrom(Class.forName(cls.getName.dropRight(1))) // 模式匹配写法 obj match { case companion if companion.isEnumCompanion => val values = companion.getClass.getMethod("values").invoke(companion).asInstanceOf[Array[? <: Enum]] // 处理逻辑 case other => }
方案B:编译期类型派生(更安全,无反射)
如果是在泛型上下文中使用,推荐用类型类派生方案,完全在编译期完成检查,无任何运行时开销:
import scala.deriving.Mirror import scala.compiletime.summonAll // 定义枚举伴生的类型类 trait EnumValues[E <: Enum]: def values: Array[E] object EnumValues: // 自动为所有枚举类型派生实例 inline given [E <: Enum](using m: Mirror.SumOf[E]): EnumValues[E] = new EnumValues[E]: override val values: Array[E] = summonAll[Tuple.Map[m.MirroredElemTypes, ValueOf]] .toList.asInstanceOf[List[ValueOf[E]]] .map(_.value) .toArray
使用时直接引入上下文即可,不需要做运行时模式匹配:
def processEnum[E <: Enum : EnumValues](): Unit = val allValues = summon[EnumValues[E]].values // 处理逻辑
内容的提问来源于stack exchange,提问作者pme
相关产品推荐
相关产品推荐

