如何在Kotlin中获取通用参数类 [英] How to get generic parameter class in Kotlin
问题描述
Firebase的snapshot.getValue()
预计如下调用:
Firebase's snapshot.getValue()
expects to be called as follows:
snapshot?.getValue(Person::class.java)
但是我想用通过类声明(即
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)
}
}
请注意,内联函数(如果公共)只能访问该类的公共成员.但是您可以使用该函数的两种变体,一种接收非内联的类参数并访问私有内部,而另一种内联帮助函数根据推断的类型参数进行验证:
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屋!