我正在尝试解析Kotlin中的字节流,其中模式是一系列opCode字节,后跟基于opCode的任意字节。因此,我首先建立了一个枚举,例如:
enum class OpCode(val code:Byte) {
foo(1),
bar(2),
yak(3),
}
因此,当我构建解析循环时,我想编写类似以下内容的
:while(stream.available() > 0) {
val opCode = stream.read().toByte()
when (opCode) {
OpCode.foo.code -> { // do foo stuff }
OpCode.bar.code -> { // do bar stuff }
OpCode.yak.code -> { // do yak stuff }
}
}
让我烦恼的是,我不得不不断地将.code
放在那儿。我宁愿做类似的事情:
val opCode = OpCode(stream.read().toByte())
但是它告诉我无法实例化枚举实例。有没有更惯用的方式来做到这一点?
答案 0 :(得分:2)
您可以向枚举添加伴侣,以添加用于查找相关枚举值的功能:
enum class OpCode(val code: Byte) {
Foo(1),
Bar(2),
Yak(3);
companion object {
fun of(code: Byte) = values().find { it.code == code }
?: throw IllegalAccessException("")
}
}
像这样使用:
while (stream.available() > 0) {
val opCode = OpCode.of(stream.read().toByte())
when (opCode) {
OpCode.Foo -> {}
OpCode.Bar -> {}
OpCode.Yak -> {}
}
}
答案 1 :(得分:1)
@ s1m0nw1答案的替代方法,使搜索一次:
interface EnumCodesMap<E : Enum> {
fun values(): Array<E>
val codesMap = values().associate { it.code to it }
}
enum class OpCode(val code: Byte) {
Foo(1),
Bar(2),
Yak(3);
companion object : EnumCodesMap<OpCode>
}
...
val opCode = OpCode.codesMap[stream.read().toByte()]
请注意,此类内容无法内置,因为您可以使用相同的code
具有多个值:
enum class OpCode(val code: Byte) {
Foo(1),
Bar(1)
}
编辑:您可以提取它以支持多个枚举,但是要有一些技巧:
inline fun <reified E : Enum<E>, K> EnumCodesMap(crossinline getKey: (E) -> K) = object : EnumCodesMap<E, K> {
override val codesMap = enumValues<E>().associate { getKey(it) to it }
}
interface EnumCodesMap<E : Enum<E>, K> {
val codesMap: Map<K, E>
}
enum class OpCode(val code: Byte) {
Foo(1),
Bar(2),
Yak(3);
companion object : EnumCodesMap<OpCode, Byte> by EnumCodesMap({ it.code })
}