Scala 3.4实现EnumMap:约束枚举类型参数与获取案例数
Scala 3.4 实现 EnumMap 的核心问题解决方案
想要在Scala 3.4中实现类似java.util.EnumMap的集合,现有初始代码如下,但存在两个待解决的问题:
import scala.reflect.ClassTag class EnumMap[K <: scala.reflect.Enum, V](using ctV: ClassTag[V]) { val capacity: Int = ??? // 如何获取K对应的枚举案例总数? private val backingArray: Array[V] = ctV.newArray(capacity); def get(k: K): V = backingArray(k.ordinal); def put(k: K, v: V): Unit = backingArray(k.ordinal) = v; }
待解决问题:
- 约束类型参数
K仅接受枚举类型(如自定义的Color),而非枚举的具体案例类型(如Color.Red.type); - 不通过运行时操作,直接从编译器获取
K对应的枚举案例总数。
问题1:约束K为枚举类型而非案例类型
Scala 3中,枚举案例的单例类型(如Color.Red.type)也会实现scala.reflect.Enum,原有的K <: scala.reflect.Enum约束无法区分枚举类型和案例类型。我们可以通过Scala 3内置的scala.Enum.Values[K]类型类来约束——只有真正的枚举类型(如Color)能自动生成该类型类的实例,案例类型无法满足此约束。
问题2:编译时获取枚举案例总数
scala.Enum.Values[K]类型类在编译阶段就能获取枚举的所有案例数组,直接取数组长度即可得到案例总数,完全不需要运行时反射操作。
完整实现代码
import scala.reflect.ClassTag import scala.Enum.Values class EnumMap[K <: scala.Enum, V](using ctV: ClassTag[V], enumValues: Values[K]) { // 编译时直接获取枚举案例总数 val capacity: Int = enumValues.values.length private val backingArray: Array[V] = ctV.newArray(capacity) def get(k: K): V = backingArray(k.ordinal) def put(k: K, v: V): Unit = backingArray(k.ordinal) = v } // 测试用枚举定义 enum Color: case Red, Green, Blue // 使用示例 object EnumMapDemo extends App { val colorMap = new EnumMap[Color, String] colorMap.put(Color.Red, "红色") colorMap.put(Color.Green, "绿色") println(colorMap.get(Color.Red)) // 输出:红色 }
关键说明
K <: scala.Enum+Values[K]的组合约束,确保只有枚举类型能被传入,若尝试传入案例类型(如Color.Red.type),编译器会直接报错,提示找不到对应Values实例;enumValues.values.length从编译时生成的枚举值数组取长度,避免了运行时反射的性能开销;- 核心逻辑和
java.util.EnumMap一致,基于枚举的ordinal值直接操作底层数组,保证存取效率。
内容的提问来源于stack exchange,提问作者Readren
相关产品推荐
相关产品推荐

