Kotlin中多Enum位标志的EnumSet与UInt互转扩展方法冲突求助
解决Kotlin EnumSet转UInt的平台声明冲突问题
问题原因
你遇到的错误是因为JVM泛型类型擦除导致的:ReadFlags和WriteFlags都是EnumSet的类型别名,在JVM层面泛型参数会被擦除,两个asUInt方法的签名都会变成asUInt(Ljava/util/EnumSet;)I,从而引发平台声明冲突。
解决方案
方案1:用@JvmName注解区分JVM方法名
直接给两个扩展方法添加不同的@JvmName,让JVM层面的方法名唯一:
enum class ReadFlag(val bits: UInt) { DATA_READY(1u), BUSY(2u) } typealias ReadFlags = EnumSet<ReadFlag> enum class WriteFlag(val bits: UInt) { UART_RESET(1u), BUSY(2u), PAGE_DATA(4u) } typealias WriteFlags = EnumSet<WriteFlag> @JvmName("readFlagsAsUInt") fun ReadFlags.asUInt(): UInt = this.fold(0u) { acc, next -> acc or next.bits } @JvmName("writeFlagsAsUInt") fun WriteFlags.asUInt(): UInt = this.fold(0u) { acc, next -> acc or next.bits }
方案2:通用接口+泛型扩展(推荐,避免重复代码)
定义一个统一的接口规范位标志枚举,再通过泛型扩展实现通用转换逻辑,同时利用reified泛型避免类型擦除问题:
// 定义位标志接口,统一bits属性 interface BitFlag { val bits: UInt } // 让所有位标志枚举实现该接口 enum class ReadFlag(override val bits: UInt) : BitFlag { DATA_READY(1u), BUSY(2u) } enum class WriteFlag(override val bits: UInt) : BitFlag { UART_RESET(1u), BUSY(2u), PAGE_DATA(4u) } // 通用泛型扩展方法,reified确保类型信息不被擦除 inline fun <reified T : Enum<T> & BitFlag> EnumSet<T>.asUInt(): UInt = fold(0u) { acc, flag -> acc or flag.bits }
使用时无需额外类型指定,Kotlin会自动推导:
val readSet = EnumSet.of(ReadFlag.DATA_READY) val readUInt = readSet.asUInt() // 结果为1u val writeSet = EnumSet.of(WriteFlag.UART_RESET, WriteFlag.PAGE_DATA) val writeUInt = writeSet.asUInt() // 结果为5u
这个方案的优势在于:无需为每个枚举重复编写转换逻辑,新增位标志枚举只需实现BitFlag接口即可复用asUInt方法,同时完全避免了JVM签名冲突问题。
内容的提问来源于stack exchange,提问作者Josh Brown
相关产品推荐
相关产品推荐

