2

我知道 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)?

我已经做了各种尝试来让这个工作,但我还没有成功。

问题:

  1. 为什么我不能在构造函数参数中传递 ofType: Class 但我可以在函数参数中传递?

  2. 有谁知道如何修理它?

  3. 是否有任何问题,无论是领域还是其他,我正在做的事情似乎确实有效并且我的所有测试仍然通过?

  4. 有没有人对此有更好的解决方案,例如使用 kotlin 扩展方法?

谢谢,保罗。

4

1 回答 1

2

实际上,如果您将类传递给超类,那么您不再需要为您的函数使用模板参数。

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)
于 2018-07-05T10:23:18.167 回答