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

Kotlin:如何确保枚举全组合有返回值且避免嵌套when?

解决方案

针对多枚举组合的价格映射需求,既要保证所有组合被覆盖的校验,又避免嵌套when的繁琐,有两种实用方案可选:

方案1:运行时全覆盖校验的HashMap映射

用数据类封装套餐组合,配合HashMap存储价格,同时在初始化时遍历所有枚举的笛卡尔积,强制校验每个组合都有对应的价格。这种方式代码简洁,开发阶段就能快速发现遗漏,无需手写大量分支。

enum class Meat { Ham, Bacon, Steak }
enum class Drink { Milk, OJ, Coffee, Tea }
enum class Eggs { Scrambled, Fried, OverEasy }

data class ComboMeal(val meat: Meat, val drink: Drink, val eggs: Eggs)

// 定义所有套餐的价格映射
private val comboPriceMap: Map<ComboMeal, Double> = mapOf(
    ComboMeal(Meat.Ham, Drink.Milk, Eggs.Scrambled) to 10.77,
    ComboMeal(Meat.Ham, Drink.Milk, Eggs.Fried) to 11.22,
    // ... 补充所有其他组合的价格
)

// 初始化时校验所有组合是否都有价格
init {
    // 生成所有可能的套餐组合(枚举笛卡尔积)
    val allPossibleCombos = Meat.values().flatMap { meat ->
        Drink.values().flatMap { drink ->
            Eggs.values().map { eggs -> ComboMeal(meat, drink, eggs) }
        }
    }
    // 找出未定义价格的组合
    val missingCombos = allPossibleCombos.filterNot { comboPriceMap.containsKey(it) }
    // 如果有遗漏,抛出异常终止启动
    require(missingCombos.isEmpty()) { "未定义价格的套餐组合:$missingCombos" }
}

fun getComboPrice(meat: Meat, drink: Drink, eggs: Eggs): Double {
    // 直接从映射中取值,由于初始化时已校验,不会出现KeyNotFound
    return comboPriceMap.getValue(ComboMeal(meat, drink, eggs))
}

优点

  • 代码结构清晰,无需维护大量when分支
  • 开发阶段启动时就会报错,避免运行时出现未定义价格的情况
  • 枚举新增值时,初始化校验会自动检测到遗漏的组合

缺点

  • 校验发生在运行时而非编译期,但开发阶段的启动校验已经足够提前发现问题

方案2:代码生成自动生成穷尽式when分支

利用Kotlin的枚举遍历能力,编写代码生成工具(比如用KotlinPoet)自动生成所有组合的when分支,让编译器直接做穷尽性检查。这种方式能获得编译期的严格校验,无运行时开销。

核心思路

  1. 遍历所有枚举的values(),生成所有可能的笛卡尔积组合
  2. 自动生成包含所有组合分支的getComboPrice函数代码
  3. 生成的代码会让编译器强制检查是否覆盖所有组合,遗漏时直接编译报错

生成后的代码示例:

fun getComboPrice(meat: Meat, drink: Drink, eggs: Eggs): Double {
    return when (Triple(meat, drink, eggs)) {
        Triple(Meat.Ham, Drink.Milk, Eggs.Scrambled) -> 10.77
        Triple(Meat.Ham, Drink.Milk, Eggs.Fried) -> 11.22
        Triple(Meat.Ham, Drink.Milk, Eggs.OverEasy) -> 11.55
        // ... 自动生成所有组合的分支
    }
}

优点

  • 编译期严格校验所有组合是否被覆盖,无运行时风险
  • 无需手动编写大量重复的when分支

缺点

  • 需要维护代码生成工具,适合枚举结构稳定、不频繁变动的场景

方案选择建议

  • 如果枚举可能频繁新增或修改,优先选方案1,维护成本更低
  • 如果需要最严格的编译期校验,且枚举结构稳定,优先选方案2

内容的提问来源于stack exchange,提问作者Tim Reistetter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 04:45:31