Ric*_*rdo 4 generics android kotlin firebase-realtime-database
我想从泛型类型获取类属性T.我决定延伸到Any但是我收到了一个错误.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html#extension-properties
我有以下代码:
class FirebaseDBRepo<T : Any>(val child:String) {
private var callback: FirebaseDatabaseRepositoryCallback<T>? = null
private val ref: DatabaseReference
private val listener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
//T::class.java is showing the error cannot use t as reified type parameter use class instead
val gameDS = dataSnapshot.getValue(T::class.java)
callback!!.onSuccess(gameDS!!)
}
override fun onCancelled(databaseError: DatabaseError) {
}
}
init {
ref = FirebaseDatabase.getInstance().reference.child(child)
}
fun addListener(callback: FirebaseDatabaseRepositoryCallback<T>) {
this.callback = callback
ref.addValueEventListener(listener)
}
fun removeListener() {
ref.removeEventListener(listener)
}
}
Run Code Online (Sandbox Code Playgroud)
Zoe*_*Zoe 12
您只能在已知的变量上获取该类.在java中也发生了同样的事情,但是消息略有不同:
public <T> void x(){
T t = T.class.newInstance();
}
Run Code Online (Sandbox Code Playgroud)
在Java中,你可以解决这个问题:
public <T> void x(Class<T> cls){
T t = cls.newInstance();
}
Run Code Online (Sandbox Code Playgroud)
这同样适用于Kotlin和任何电话.在大多数情况下,您需要获取类实例.但是,Kotlin使用关键字支持reified泛型,但仅支持内联泛型函数.你可以传递一个类,但在函数中,只需使用reified关键字就可以了.
因为你不能声明一个具有reified泛型的类,这意味着这是无效的:
class SomeClass<reified T>
Run Code Online (Sandbox Code Playgroud)
但它对内联函数有效,这意味着你可以这样做:
inline fun <reified T> someFunction()
Run Code Online (Sandbox Code Playgroud)
所以你有两个选择.但是,由于您扩展了一个监听器,因此将该泛型添加到该函数的第一个选项不是一个选项.您不能使用泛型覆盖非泛型方法.它不会编译.
这留下了第二种选择,不幸的是,这种选择相当苛刻; 将类传递给构造函数.所以看起来应该是这样的:
class FirebaseDBRepo<T : Any>(val child: String, private val cls: Class<T>) {
Run Code Online (Sandbox Code Playgroud)
现在,我不使用Firebase,所以我不知道你要传递哪些类,所以对于下一个例子,我只是使用String.
Kotlin支持某种类型的最小化,而不需要转换为原始类型.这个:
val t = FirebaseDBRepo<String>("", String::class.java)
Run Code Online (Sandbox Code Playgroud)
可以缩短到这个:
val t = FirebaseDBRepo("", String::class.java)
Run Code Online (Sandbox Code Playgroud)
两种情况下的推断类型都是FirebaseDBRepo<String>.
小智 8
由于您在 JVM 上运行,因此类型擦除是一回事。这意味着(简单来说),在编译期间,泛型会被简单地忽略。因此,您无法获得 T 的类,因为 JVM 甚至不知道您所说的“T”是什么意思。
在某些情况下,Kotlin 使用一个聪明的技巧来解决这个限制。当您使用内联函数时,编译器不会调用您定义的函数,而是将整个函数体复制到您调用它的位置。这只能用于内联函数。不是上课。
有一个很困难的解决方法:只需添加 private val classT: Class<T>
到构造函数并改用参数!
| 归档时间: |
|
| 查看次数: |
3831 次 |
| 最近记录: |