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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 08:37:52