Kotlin如何让函数接受任意派生类的KClass参数?
如何让Kotlin函数接受任意派生类的KClass类型参数?
问题重现
你编写的代码尝试让函数接收任意T派生类的KClass数组,但编译器抛出类型不匹配错误:
原代码:
import kotlin.reflect.KClass fun <T: Any> test(arr: Array<KClass<T>>) { print(arr) } fun main() { test<Number>(arrayOf(Int::class, Short::class)) }
错误信息:
Type mismatch: inferred type is Number but Int was expected Type mismatch: inferred type is Short but Int was expected Type mismatch: inferred type is Number but Short was expected Type mismatch: inferred type is Int but Short was expected Type mismatch: inferred type is KClass<Short> but KClass<Int> was expected Type mismatch: inferred type is KClass<Int> but KClass<Short> was expected Type mismatch: inferred type is KClass<Short> but KClass<Int> was expected
问题原因
核心问题在于容器类型的协变性:
KClass本身是协变的(定义为KClass<out T : Any>),这意味着KClass<Int>可以视为KClass<out Number>的子类型;- 但
Array是不变类型,Array<KClass<Number>>只能接收KClass<Number>类型的元素,无法直接容纳KClass<Int>或KClass<Short>这类子类型实例。
解决方案
有两种常用的修改方式:
方案1:给数组和KClass添加协变投影
修改函数参数为Array<out KClass<out T>>,通过out投影允许容器接收协变类型:
import kotlin.reflect.KClass fun <T: Any> test(arr: Array<out KClass<out T>>) { print(arr) } fun main() { test<Number>(arrayOf(Int::class, Short::class)) }
- 第一个
out表示我们只读取数组元素(不修改数组),允许数组本身协变; - 第二个
out表示允许传入T子类的KClass实例。
方案2:改用List代替Array
Kotlin中的List默认是协变的(List<out E>),直接替换数组为List即可:
import kotlin.reflect.KClass fun <T: Any> test(arr: List<KClass<out T>>) { print(arr) } fun main() { test<Number>(listOf(Int::class, Short::class)) }
这种方式更符合Kotlin的惯用写法,List的协变特性天然适配这种场景。
内容的提问来源于stack exchange,提问作者kennarddh
相关产品推荐
相关产品推荐

