如何在Kotlin中获得generics参数类
Firebase的snapshot.getValue()
预计将被调用,如下所示:
snapshot?.getValue(Person::class.java)
不过,我想用一个通过类声明传递给类的generics参数替换Person
DataQuery
并使用该generics参数来做这样的事情:
snapshot?.getValue(T::class.java)
但是当我尝试,我得到一个错误说明
只有类可以用在类文字的左侧
是否有可能像在C#中的generics参数提供一个类的约束,还是有一些其他的语法,我可以用来获取generics参数的types信息?
你需要的是通用参数的修饰符,你可以在这里阅读。 https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters所以,如果你做这样的事情:
inline fun T.logTag() = T::class.java.simpleName
你将得到实际的调用者类的名字,而不是“对象”。
对于具有generics参数T的类,不能这样做,因为JVM没有types信息,因为JVM会删除types信息。 因此这样的代码不能工作:
class Storage { val snapshot: Snapshot? = ... fun retrieveSomething(): T? { return snapshot?.getValue(T::class.java) // ERROR "only classes can be used..." } }
但是,如果T的types在内联函数中被指定和使用,则可以使其工作:
class Storage { val snapshot: Snapshot? = ... inline fun retrieveSomething(): T? { return snapshot?.getValue(T::class.java) } }
请注意,内联函数如果公开只能访问该类的公共成员。 但是可以有两个函数变体,一个接收一个不是内联的类参数,并且访问私有内部函数,另一个内联辅助函数从推断的types参数中进行确定:
class Storage { private val snapshot: Snapshot? = ... fun retrieveSomething(ofClass: Class): T? { return snapshot?.getValue(ofClass) } inline fun retrieveSomething(): T? { return retrieveSomething(T::class.java) } }
您也可以使用KClass
而不是Class
这样只有Kotlin的调用者才可以使用MyClass::class
而不是MyClass::class.java
如果您希望类与generics上的内联方法配合使用(意味着类Storage
只存储typesT
对象):
class Storage { val snapshot: Snapshot? = ... inline fun retrieveSomething(): R? { return snapshot?.getValue(R::class.java) } }
内联函数中通用types的链接: https : //kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters