如何在 Kotlin 中获取泛型参数类 [英] How to get generic parameter class in Kotlin

查看:83
本文介绍了如何在 Kotlin 中获取泛型参数类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Firebase 的 snapshot.getValue() 期望按如下方式调用:

Firebase's snapshot.getValue() expects to be called as follows:

snapshot?.getValue(Person::class.java)

但是我想用通过类声明传递到类中的泛型参数替换 Person,即

However I would like to substitute Person with a generic parameter that is passed into the class via the class declaration i.e.

class DataQuery<T : IModel> 

并使用该通用参数执行以下操作:

and use that generic parameter to do something like this:

snapshot?.getValue(T::class.java)

但是当我尝试这样做时,我收到一个错误提示

but when I attempt that I get an error stating that

只有类可以用在类文字的左侧

only classes can be used on the left-hand side of a class literal

是否可以像在 C# 中那样对泛型参数提供类约束,或者是否可以使用其他一些语法来获取泛型参数的类型信息?

Is it possible to provide a class constraint on the generic parameter like in C# or is there some other syntax I can use to get the type info for the generic param?

推荐答案

对于具有泛型参数 T 的类,您不能这样做,因为您没有 T 的类型信息,因为 JVM 擦除了类型信息.因此这样的代码不能工作:

For a class with generic parameter T, you cannot do this because you have no type information for T since the JVM erases the type information. Therefore code like this cannot work:

class Storage<T: Any> {
    val snapshot: Snapshot? = ...

    fun retrieveSomething(): T? {
        return snapshot?.getValue(T::class.java) // ERROR "only classes can be used..."
    }
}

但是,如果 T 的类型被具体化并在一个内联函数中使用,你就可以完成这项工作:

But, you can make this work if the type of T is reified and used within an inline function:

class Storage {
    val snapshot: Snapshot? = ...

    inline fun <reified T: Any> retrieveSomething(): T? {
        return snapshot?.getValue(T::class.java)
    }
}

注意内联函数 if public 只能访问类的公共成员.但是您可以有两个函数变体,一个接收非内联的类参数并访问私有内部结构,另一个内联辅助函数从推断的类型参数中进行具体化:

Note that the inline function if public can only access public members of the class. But you can have two variants of the function, one that receives a class parameter which is not inline and accesses private internals, and another inline helper function that does the reification from the inferred type parameter:

class Storage {
    private val snapshot: Snapshot? = ...

    fun <T: Any> retrieveSomething(ofClass: Class<T>): T? {
        return snapshot?.getValue(ofClass)
    }

    inline fun <reified T: Any> retrieveSomething(): T? {
        return retrieveSomething(T::class.java)
    }
}

您也可以使用 KClass 代替 Class 以便仅使用 Kotlin 的调用者可以使用 MyClass::class 而不是 <代码>MyClass::class.java

You can also use KClass instead of Class so that callers that are Kotlin-only can just use MyClass::class instead of MyClass::class.java

如果你想让类与泛型上的内联方法合作(意味着类Storage只存储T类型的对象):

If you want the class to cooperate with the inline method on the generics (meaning that class Storage only stores objects of type T):

class Storage <T: Any> {
    val snapshot: Snapshot? = ...

    inline fun <reified R: T> retrieveSomething(): R? {
        return snapshot?.getValue(R::class.java)
    }
}

内联函数中具体化类型的链接:https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters

The link to reified types in inline functions: https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters

这篇关于如何在 Kotlin 中获取泛型参数类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆