在kotlin中,如何制作一个使用枚举键映射的类

时间:2019-06-17 06:23:06

标签: generics kotlin enums

或者换句话说,如何在我的类中构造一个内部EnumMap,其中EnumMap键类型由调用者选择的Enum设置。

我希望有这样的代码:

enum MY_FLAGS { FLAG1, FLAG2, FLAG3 }
val myProfiler = Profiler<MY_FLAGS>()
myProfiler.profile(FLAG1) {
  longRunningOperation() 
  // the time to execute longRunningOperation 
  // is accumulated in myProfiler's EnumMap.
}

我有一堂课,可以追踪各种柜台。这些计数器键始终来自相同的Enum类。因此,我想构造计数器类实例以仅处理该特定的Enum。

到目前为止,我有class Profiler<in E:Class<Enum<*>>>(private val clazz: E) {感觉非常接近,但事实并非如此,因为当我尝试使用探查器类函数递增一个计数器时,我无法用E!

例如,是否未将TempEnum硬编码为:

val enumMap = EnumMap<TempEnum, MutableList<TimeDuration>>(TempEnum::class.java).apply {
  putAll(TempEnum.values().map {
    it to mutableListOf<TimeDuration>()
  })
}

然后,编译器开始抱怨in vs out vs invariant,这就是我变得模糊的地方。

1 个答案:

答案 0 :(得分:2)

要构造一个可以将通用Enum作为类型参数的类,可以执行以下操作:

class Profiler<E : Enum<*>> {
   val counter = mutableMapOf<E, Int>()

   fun profile(key: E, block: (E) -> Unit) {
        block(key)
        // increase counter
    }
}

可以使用以下方法调用它:

fun main() {
    val profiler = Profiler<MyFlags>()
    profiler.profile(MyFlags.Flag2) {
        println("$it - ${profiler.counter[it]}")
    }
}

要限制Profiler仅接受MyFlags作为有效的类型参数,可以按如下所示更改类签名:

class Profiler<E : Enum<MyFlags>> {