问题描述
我想根据具体化的类型参数返回不同的类型。我尝试使用重载,但重载解析似乎不正确。
我的目标是在运行时存储一组接近的类型,如下所示:
sealed interface Type<T> {
object Int: Type<kotlin.Int>
object Boolean: Type<kotlin.Boolean>
}
inline fun<reified T> get() : Type<T> = getImpl(null as T?)
fun getImpl(a: Int?) : Type<Int> = Type.Int
fun getImpl(a: Boolean?) : Type<Boolean> = Type.Boolean
fun <T>getImpl(a: T?) : Type<T> = error("Unsupported type")
fun main() {
println(getImpl(null as Int?)) // return Type.Int as expected
println(get<Int>()) // Same as above after get is inlined but throws!
}
目标是让一些泛型类采用 Type<T>
参数并保证 T 在闭集中。它还允许在运行时测试泛型类型 T
(解决方法类型擦除)。
我宁愿避免让客户端明确指定 Type.Int
或使用未经检查的强制转换来实现,例如:
inline fun<reified T> getUncheckedCast() : Type<T> =
when (T::class) {
Int::class -> Type.IntType as Type<T>
Boolean::class -> Type.BooleanType as Type<T>
else -> error("Unsupported type")
}
解决方法
我认为你的最后一个代码块是最好的解决方案。尽管您的 get
函数被具体化,但该类型仍然是泛型的,因此编译器会将重载解析为引发错误的泛型。您无法让编译器选择在运行时调用哪个重载。它总是在编译时被选中。
根据 Kotlin documentation,reified
参数的唯一区别在于其运行时类可用:
4.5.2 具体化的类型参数加载测试
内联函数声明的类型参数(并且只有那些)可以使用相应的关键字进行具体化。 reified 类型参数是函数作用域内的 runtime-available 类型,详见相应章节。
它没有指定在函数内联时替换类型。
这意味着 reified
正在为隐式传递具体化类型的 KClass
加糖:
inline fun <reified T>f() = T.class
// is desugared to
inline fun <T>f(__TKClass : KClass<T>) = __TKClass
因此重载解析集不受具体化类型的影响。