为什么我的Realm Kotlin Generics解决方法无法按预期工作?

时间:2018-07-05 10:13:18

标签: generics kotlin realm

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

我试图通过在构造函数中传递类类型而不是函数param来进一步改善这一点:

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:类,但可以在函数param中传递?

  2. 有人知道如何解决吗?

  3. Realm是否有问题,我在做什么,因为它似乎可以正常工作并且我的所有测试仍然通过?

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

谢谢, 保罗。

1 个答案:

答案 0 :(得分: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)