我知道 Realm 还不直接支持泛型。我一直在尝试想出一个解决方法,因为它将极大地减少我的项目中的重复代码。 (我有许多扩展基础存储库的存储库和许多仅因 RealmObject 扩展类型而异的函数)
我有一个相当好的解决方案:
open class BaseRepository(private val realm: Realm) {
fun <T : RealmModel> get(ofType: Class<T>, id: Long): T? {
return realm.where(ofType).equalTo("id", id).findFirst()
}
}
这可以由我的从 BaseRepository 继承的存储库调用,如下所示:
customRepository.get(CustomType::class.java, id)
我尝试通过在构造函数中传递类类型而不是函数参数来进一步改进这一点:
open class BaseRepository<T : RealmModel?>(private val realm: Realm, private val ofType: Class<T>) {
fun <T : RealmModel> get(id: Long): T? {
return realm.where(ofType).equalTo("id", id).findFirst()
}
}
上面有以下编译时错误:
Type mismatch.
Required: T#1 (type parameter of com.acme.data.repository.BaseRepository.get)?
Found: T#2 (type parameter of com.acme.data.repository.BaseRepository)?
我已经做了各种尝试来让它工作,但到目前为止我还没有成功。
问题:
为什么我不能在构造函数参数中传递 ofType: Class,但可以在函数参数中传递?
有人知道如何解决吗?
我正在做的事情是否存在任何问题,无论是 Realm 还是其他方面,因为它似乎有效并且我的所有测试仍然通过?
有没有人对此有更好的解决方案,例如使用 kotlin 扩展方法?
谢谢, 保罗。
最佳答案
实际上,如果您将类传递给父类(super class),则您的函数不再需要使用模板参数。
open class BaseRepository<T : RealmModel>(private val realm: Realm, private val ofType: Class<T>) {
fun get(id: Long): T? =
realm.where(ofType).equalTo("id", id).findFirst()
}
一个有趣的花絮是,使用 Kotlin,您可以减少 ::class.java
使用inline <reified T>
.
open class BaseRepository(private val realm: Realm) {
inline fun <reified T : RealmModel> get(id: Long): T? =
realm.where(T::class.java).equalTo("id", id).findFirst()
}
或者,如果您使用的是较新版本的 Realm (4.3.1+),那么您可以将其更改为
import io.realm.kotlin.where
open class BaseRepository(private val realm: Realm) {
inline fun <reified T : RealmModel> get(id: Long): T? =
realm.where<T>().equalTo("id", id).findFirst()
}
我只是向您提出想法,但您可以从技术上将其变成扩展函数
inline fun <reified T : RealmModel> Realm.get(id: Long): T? =
where<T>().equalTo("id", id).findFirst()
现在你可以做
val dog = realm.get<Dog>(12L)
关于generics - 为什么我的 Realm Kotlin 泛型解决方法没有按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51188698/