Kotlin中如何检查枚举列表的枚举组合并获得编译器完整性校验支持
解决方案
核心思路是利用Kotlin密封类/密封接口的when穷尽检查特性,将所有需要判定的错误场景(包括单个枚举、枚举组合、无错误状态)全部封装为密封类的子类,再统一实现从枚举集合到错误场景的转换逻辑,即可同时满足优先级判定、组合检查、编译器穷尽校验三个需求。
实现步骤
- 定义密封接口枚举所有错误场景
sealed interface ErrorScene { // 单个错误场景 object TechnicalError : ErrorScene object DocumentError : ErrorScene object SignatureError : ErrorScene object MagicError : ErrorScene // 组合错误场景 object DocumentAndSignatureError : ErrorScene // 无错误场景 object NoError : ErrorScene }
- 实现枚举集合到错误场景的转换扩展方法,在该方法内维护判定优先级
fun List<ErrorCode>.toErrorScene(): ErrorScene = when { // 优先级最高:技术错误 contains(ErrorCode.TECHNICAL_ERROR) -> ErrorScene.TechnicalError // 次优先级:文档+签名组合错误 containsAll(listOf(ErrorCode.DOCUMENT_ERROR, ErrorCode.SIGNATURE_ERROR)) -> ErrorScene.DocumentAndSignatureError // 单个错误优先级 contains(ErrorCode.DOCUMENT_ERROR) -> ErrorScene.DocumentError contains(ErrorCode.SIGNATURE_ERROR) -> ErrorScene.SignatureError contains(ErrorCode.MAGIC_ERROR) -> ErrorScene.MagicError // 兜底无错误 else -> ErrorScene.NoError }
- 业务代码使用时直接对转换后的
ErrorScene做when判定,编译器会自动校验分支覆盖情况
fun main() { val errorList: List<ErrorCode> = listOf( ErrorCode.DOCUMENT_ERROR, ErrorCode.SIGNATURE_ERROR, ErrorCode.MAGIC_ERROR, ) when (errorList.toErrorScene()) { ErrorScene.TechnicalError -> println("Technical Error") ErrorScene.DocumentAndSignatureError -> println("Document and Signature Error") ErrorScene.DocumentError -> println("Document Error") ErrorScene.SignatureError -> println("Signature Error") ErrorScene.MagicError -> println("Magic Error") ErrorScene.NoError -> println("No Errors") } }
可选优化
- 性能优化:如果枚举数量较多,将
List<ErrorCode>替换为EnumSet<ErrorCode>,枚举专属集合的contains/containsAll操作时间复杂度为O(1),远高于普通列表的O(n),判定逻辑无需修改。 - 新增枚举漏处理校验:如果需要保证新增
ErrorCode枚举值时不会漏处理,可在转换方法开头添加单枚举穷尽检查:
fun List<ErrorCode>.toErrorScene(): ErrorScene { // 新增ErrorCode时编译器会自动提示补全该when分支,避免漏处理 for (code in this) { when (code) { ErrorCode.TECHNICAL_ERROR, ErrorCode.DOCUMENT_ERROR, ErrorCode.SIGNATURE_ERROR, ErrorCode.MAGIC_ERROR -> Unit } } // 原有判定逻辑不变 return when { contains(ErrorCode.TECHNICAL_ERROR) -> ErrorScene.TechnicalError // ...其余逻辑 else -> ErrorScene.NoError } }
内容的提问来源于stack exchange,提问作者Rockyy
相关产品推荐
相关产品推荐

