Kotlin 中具体化泛型的重载解析
Overload resolution of reified generic in Kotlin
我想 return 不同的类型取决于具体化的类型参数。我尝试使用重载,但重载解析似乎不正确。
我的目标是像这样在运行时存储一组接近的类型:
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
函数已具体化,但该类型仍然是通用的,因此编译器会将重载解析为引发错误的通用类型。您无法让编译器 select 在运行时调用哪个重载。它总是在编译时 selected。
根据 Kotlin documentation,参数 reified
的唯一区别是其运行时 class 可用:
4.5.2 Reified type parametersLoad tests
Type parameters of inline function declarations (and only those) can be declared reified using the corresponding keyword. A reified type parameter is a runtime-available type inside the function scope, see the corresponding section for details.
没有指定内联函数时替换类型。
这意味着 reified
正在为隐式传递具体化类型的 KClass
加糖:
inline fun <reified T>f() = T.class
// is desugared to
inline fun <T>f(__TKClass : KClass<T>) = __TKClass
因此重载决议集不受具体化类型的影响。
我想 return 不同的类型取决于具体化的类型参数。我尝试使用重载,但重载解析似乎不正确。
我的目标是像这样在运行时存储一组接近的类型:
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
函数已具体化,但该类型仍然是通用的,因此编译器会将重载解析为引发错误的通用类型。您无法让编译器 select 在运行时调用哪个重载。它总是在编译时 selected。
根据 Kotlin documentation,参数 reified
的唯一区别是其运行时 class 可用:
4.5.2 Reified type parametersLoad tests
Type parameters of inline function declarations (and only those) can be declared reified using the corresponding keyword. A reified type parameter is a runtime-available type inside the function scope, see the corresponding section for details.
没有指定内联函数时替换类型。
这意味着 reified
正在为隐式传递具体化类型的 KClass
加糖:
inline fun <reified T>f() = T.class
// is desugared to
inline fun <T>f(__TKClass : KClass<T>) = __TKClass
因此重载决议集不受具体化类型的影响。