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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 23:15:53