如何在Kotlin中检查泛型类型?

mlmc2os5  于 2022-12-13  发布在  Kotlin
关注(0)|答案(4)|浏览(210)

我上课:

class Generic<T : SuperType>() { ... }

这段代码是不正确的,但请将s转换为T类型:

fun typeCheck(s: SuperType) {
    when(s) {
        is T -> // Do something
    }
}

如果用途:s as T-此强制转换将显示警告(不安全的强制转换)。
如何检查s是否为T类型?

1hdlvixo

1hdlvixo1#

如果你需要检查某个东西是否是T的泛型类型,你需要有一个Class<T>的示例来进行检查。这是Java中的一种常见技术,但是在Kotlin中,我们可以使用一个内联的工厂方法来获取类对象。

class Generic<T : Any>(val klass: Class<T>) {
    companion object {
        inline operator fun <reified T : Any>invoke() = Generic(T::class.java)
    }

    fun checkType(t: Any) {
        when {
            klass.isAssignableFrom(t.javaClass) -> println("Correct type")
            else -> println("Wrong type")
       }

    }
}

fun main(vararg args: String) {
    Generic<String>().checkType("foo")
    Generic<String>().checkType(1)
}
r55awzrz

r55awzrz2#

泛型类型在运行时不会在JVM上具体化,所以在Kotlin中没有办法这样做。警告是正确的,因为编译器不可能生成任何在强制转换完成时会失败的指令,所以强制转换是未检查的,这意味着程序可能会或可能不会在稍后的某个时候中断。
一个可能有用的相关特性是内联函数中的具体化类型参数。尽管类不能有具体化的类型参数,所以如果你对你的用例做更多的阐述,我可以试着帮助你实现你似乎需要的。

8ljdwjyq

8ljdwjyq3#

我知道我有点晚了这个线程,但我只是想回顾一下 Alexandria Udalov提供的答案。
实际上,在Kotlin中确定泛型参数的类型是不可能的,除非使用内联函数并将泛型类型声明为reified
我不确定我是否能够完整、准确地回答这个问题,但我觉得我的贡献对试图这样做的人来说可能仍然是有价值的。所以,假设您有几个数据类,并且您希望检查您正在处理的是哪种类型。
您可以使用如下函数:

inline fun <reified T> checkType() = when (T::class) {
    TypeA::class -> println("TypeA")
    else -> println("Type not recognized")
}

但是,调用它的函数也必须是内联的,因此您可能必须编写类似于

inline fun <reified T> someOtherFunction(data: T) {
    checkType<T>
}

然而,如果你不能允许一个内联函数(比如说在一个接口中!),你可以通过这样的方式来“欺骗”系统,例如

class AmazingTypes {
    inline fun <reified T> checkType(genericParameter: T) = when (T::class) {
        TypeA::class -> println("TypeA")
        else -> println("Type not recognized")
    }
}

fun myAwesomeMethod(someParameter: Any) {
    val amazingClass = AmazingClass()
    amazingClass.checkType(someParameter)
}
gojuced7

gojuced74#

这也是一个例子。

inline fun <reified T: ApiResponse> parseJson(body: String): T {
    // handle OkResponse only
    val klass = T::class.java
    if (klass.isAssignableFrom(OkResponse::class.java)) {
        return T::class.java.newInstance()
    }
    // handle others
    return gson.from(body, T::class.java)
}

相关问题