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

时间:2015-10-15 10:31:32

标签: kotlin

我有课

class Generic<T : SuperType>()

并且此代码不正确

fun typeCheck(s: SuperType): Unit {
            when(s){
                is T -> //do some thin
            }
        }

但是将s投射到T s as T类型显示警告 - 不安全的演员。
如何检查s是否为T类型?

4 个答案:

答案 0 :(得分:22)

如果您需要检查某些内容是否为通用类型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)
}

答案 1 :(得分:6)

通用类型在运行时未在JVM上实现,因此在Kotlin中无法执行此操作。警告是正确的,因为编译器可能无法生成任何在转换完成时将失败的指令,因此转换是未选中的,这意味着程序可能会在某个时间点或之后中断。

可能有用的相关功能是内联函数中的reified type parameters。虽然类不能使用具体的类型参数,但如果您对用例进行详细说明,我可以尝试帮助您实现您所需的类型。

答案 2 :(得分:3)

我知道我对此线程有点迟,但是我只想回顾一下亚历山大·乌达洛夫(Alexander Udalov)提供的答案。

除非您使用内联函数并将通用类型声明为reified,否则在Kotlin中确实无法确定通用参数的类型。

不知道我是否能够完整,准确地回答这个问题,但是我觉得我的贡献对于尝试这样做的人可能仍然很有价值。因此,假设您有一些数据类,并且想检查要处理的类型。

您可以使用类似的功能:

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)
}

答案 3 :(得分:0)

这也是示例。

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)
}