【问题标题】:How to check generic type in Kotlin?如何检查 Kotlin 中的泛型类型?
【发布时间】:2015-10-15 10:31:32
【问题描述】:

我有课

class Generic<T : SuperType>()

而且这段代码不正确

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

但将 s 转换为类型 T s as T 显示警告 - 不安全的转换。
如何检查sT 类型?

【问题讨论】:

  • 字符串是最终的,为什么要使用T : String
  • @cypressious 只是一个例子

标签: kotlin


【解决方案1】:

如果您需要检查某些东西是否属于泛型类型 T,您需要有一个 Class&lt;T&gt; 的实例来检查。这是 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)
}

【讨论】:

  • 你能回答我的问题吗? stackoverflow.com/questions/47418161/…
  • 绝招!当Generic 类是抽象类时,你知道如何让它工作吗?我遇到的问题是在 invoke 运算符上实例化子对象。
  • 这不会那么容易。子类构造函数需要将Class 实例传递给超级构造函数。
【解决方案2】:

泛型类型在运行时不会在 JVM 上具体化,因此在 Kotlin 中无法做到这一点。警告是正确的,因为编译器不可能生成任何在转换完成时会失败的指令,因此未检查转换,这意味着程序可能会或可能不会在稍后的某个时候中断。

一个可能有用的相关功能是内联函数中的reified type parameters。但是,类不能具有具体的类型参数,因此,如果您对用例进行详细说明,我可以尝试帮助您实现您似乎需要的东西。

【讨论】:

    【解决方案3】:

    我知道我对这个帖子有点晚了,但我只想回顾一下 Alexander 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)
    }
    

    【讨论】:

      【解决方案4】:

      这也是一个例子。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        • 2010-09-18
        • 1970-01-01
        • 1970-01-01
        • 2020-09-18
        • 1970-01-01
        相关资源
        最近更新 更多