kotlin - 将具有任何上限的已转换泛型类型转换为非空

标签 kotlin generics casting kotlin-reified-type-parameters

我正在尝试使用一个经过修饰的type参数来检查type参数是否可为空,并根据type参数的可为性返回不同的类实现。除非空子类要求其泛型类型具有非空Any上限以具有KClass<T>构造函数参数外,此方法运行良好。
此代码按预期工作:

interface Test
class NullableT<T> : Test
class NonNullT<T> : Test

inline fun <reified T> test(): Test {
    return if (null is T) {
        NullableT<T>()
    } else {
        NonNullT<T>()
    }
}

test<String?>()::class.simpleName // NullableT
test<String>()::class.simpleName  // NonNullT
但是,此代码有一个编译器错误:
interface Test
class NullableT<T> : Test
class NonNullT<T : Any>(tClass: KClass<T>) : Test

inline fun <reified T> test(): Test {
    return if (null is T) {
        NullableT<T>()
    } else {
        NonNullT<T>(T::class) // <-- error with <T>
        // Type argument is not within its bounds. Expected: Any Found: T
    }
}
在检查!(null is T)之后,需要某种方式将T转换为具有非空的Any上限。
可以将非null的T设为可选。这有效:
interface Test
class NullableT<T> : Test
class NonNullT<T : Any> : Test

inline fun <reified T : Any> test(nullable: Boolean): Test {
    return if (nullable) {
        NullableT<T?>()
    } else {
        NonNullT<T>()
    }
}

test<String>(true)::class.simpleName // NullableT
test<String>(false)::class.simpleName // NonNullT
但是我需要一种使可为空的T不为空的方法。这是无效的:
interface Test
class NullableT<T> : Test
class NonNullT<T : Any> : Test

inline fun <reified T> test(nullable: Boolean): Test {
    return if (nullable) {
        NullableT<T>()
    } else {
        NonNullT<T!!>() // Type parameter 'T' is not an expression
    }
}

最佳答案

This的作品:

import kotlin.reflect.*
interface Test
class NullableT<T> : Test
class NonNullT<T : Any>(tClass: KClass<T>) : Test

inline fun <reified T> test(dummy: Nothing? = null): Test {
    return NullableT<T>()
}
inline fun <reified T: Any> test(): Test {
    return NonNullT<T>(T::class)
}


fun main(){
    println(test<Any>().toString())
    println(test<Any?>().toString())
    println(test<String>().toString())
    println(test<String?>().toString())
}
“但是为什么行得通呢?”我听到你在问。好吧,简单的是,这里发生的事情是Kotlin编译器更喜欢与传入参数数量匹配的函数(在这种情况下为0),而不是具有默认参数的函数,后者会导致允许传入参数的数量(换句话说,如果如果您调用带有1个参数的函数,则编译器将更喜欢带有1个参数的函数,而不是带有2个参数的函数(其中第2个参数具有默认值)。但是,由于T在2个函数中具有不同的上限,因此,如果您尝试调用test的类型不遵循首选函数的上限(在本例中为返回NonNullT的上限),编译器将退回到调用更广泛的test函数(即返回NullableT的函数)。
该解决方案有点笨拙,但遗憾的是,我认为没有其他实现方法。

关于kotlin - 将具有任何上限的已转换泛型类型转换为非空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63027333/

相关文章:

typescript - 在泛型函数中将参数回调签名推断为元组?

c# - 是否可以将字符串转换为我自己的类型?

安卓和 Kotlin : Unresolved reference: home

android - Android 8 (Oreo) 上的 GcmIntentService 崩溃

c# - 如何将对象数组转换为泛型类型数组

Java 泛型转换

php - 如何修复 PHP 中的警告非法字符串偏移

kotlin - 撰写 : placement of measurables in Layout based on measuredWidth

oop - 为什么在 Kotlin 中 Stack<Int> 可以 push(null) 而 ArrayList<Int> 不能 add(null)?

c# - 在运行时使用动态泛型参数转换泛型