Kotlin中如何将密封类实例作为函数参数传递并进行类型比较
解决方案:密封类类型的动态比较
你的核心问题在于参数类型不兼容,以及没有正确处理Kotlin密封类的反射类型匹配。下面给你几种符合需求的实现方式,从修正原有代码到更优雅的Kotlin风格实现都有:
方案1:修正原有Java Class的实现
原来的函数参数Class<MyState>是不变类型,无法直接接收State1::class.java(它的类型是Class<State1>)。我们需要将参数改为协变类型Class<out MyState>,这样就能接受密封类所有子类的Class对象了:
fun myFunction(conditionStateClass: Class<out MyState>): Boolean { val newState1 = MyState.State1("foo") val newState2 = MyState.State2 // 直接比较实例的Class对象与传入的类型 return newState1::class.java == conditionStateClass || newState2::class.java == conditionStateClass }
调用方式完全符合你的预期:
// 判断newState1或newState2是否是State1类型 val result1 = myFunction(MyState.State1::class.java) // 判断是否是State2类型 val result2 = myFunction(MyState.State2::class.java)
方案2:更优雅的Kotlin KClass实现
Kotlin自带的KClass比Java的Class更贴合Kotlin语法,不需要额外转换,代码更简洁:
import kotlin.reflect.KClass fun myFunction(conditionStateKClass: KClass<out MyState>): Boolean { val newState1 = MyState.State1("foo") val newState2 = MyState.State2 // 直接比较Kotlin类引用 return newState1::class == conditionStateKClass || newState2::class == conditionStateKClass }
调用时直接传入Kotlin类引用即可:
val result1 = myFunction(MyState.State1::class) val result2 = myFunction(MyState.State2::class)
方案3:通用类型匹配(支持子类继承场景)
如果未来你的密封类子类有继承关系(虽然密封类本身限制了子类范围,但可以兼容这种情况),可以使用isInstance方法来判断实例是否属于该类型(包括子类):
import kotlin.reflect.KClass fun myFunction(conditionStateKClass: KClass<out MyState>): Boolean { val newState1 = MyState.State1("foo") val newState2 = MyState.State2 // 判断实例是否是该类型的实例 return conditionStateKClass.isInstance(newState1) || conditionStateKClass.isInstance(newState2) }
这个方案的逻辑和前两种在当前密封类结构下结果一致,但扩展性更好。
内容的提问来源于stack exchange,提问作者Mehdi Satei
相关产品推荐
相关产品推荐

