Почему мой обход Realm Kotlin Generics не работает должным образом? - PullRequest
0 голосов
/ 05 июля 2018

Я знаю, что Realm еще не поддерживает Generics напрямую. Я пытался найти обходной путь, так как он значительно уменьшит количество дублирующегося кода в моем проекте. (У меня есть много репозиториев, которые расширяют базовый репо, и множество функций, которые отличаются только расширенным типом 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: Class в параметре конструктора, а могу в параметре функции?

  2. Кто-нибудь знает, как это исправить?

  3. Есть ли какая-либо проблема, Царство или нет, с тем, что я делаю, поскольку это, кажется, работает, и все мои тесты все еще проходят?

  4. Кто-нибудь получил лучшее решение для этого, например, используя методы расширения kotlin?

Спасибо, Пол.

1 Ответ

0 голосов
/ 05 июля 2018

На самом деле, если вы передаете класс суперклассу, вам больше не нужно использовать параметр шаблона для вашей функции.

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...