2016-12-25 2 views
0

Я пытаюсь создать набор поставщиков для объектов сферы. Вот пример структуры я пытался построить:Наследование родословной Kotlin - несоответствие типа

Интерфейс:

interface IDataProvider<out T : RealmObject> { 
    fun getRealmObject(): T 
} 

Базовый класс поставщика с функцией компаньона для поставщика типизированных конкретизации:

open abstract class BaseProvider<out T : RealmObject> constructor(protected val context: Context?) : IDataProvider<T> { 

    companion object { 
     fun <T : RealmObject, E : BaseProvider<T>> create(context: Context?): E {   
     if (something) { 
      return SomeChildProviderProvider(context) 
     } else { 
      throw TypeNotSupportedException() 
     } 
     } 
    } 
} 

А вот ребенок класс :

class SomeChildProvider(context: Context?) : BaseProvider<ChildRealmModel>(context){ 
    override fun getRealmObject(): ChildRealmModel { 
     throw UnsupportedOperationException("not implemented") 
    } 
} 

Проблема У меня есть на линии

return SomeChildProviderProvider(context) 

Несоответствие типа. Обязательно: E. Найдено: SomeChildProvider.

Я не могу понять, почему он не видит, что E на самом деле является SomeChildProvider. Спасибо.

P.S. Я знаю, что могу отдать это Е, но, на мой взгляд, в этой ситуации это не нужно. Может быть, мне не хватает чего-то очевидного здесь или, вероятно, недостатка знаний Котлина.

Update1: После первого ответа, мы поняли, что код выше, не имеет особого смысла, так как мы должны определить тип возвращения поставщика и передать его в метод создания. Первоначальная идея заключалась в том, что метод create возвращает некоторый тип, который является подтипом BaseProvider. Вот изменения, которые я сделал для того, чтобы поддержать первоначальную идею:

IDataProvider

interface IDataProvider { 
    fun execute(realm: Realm) 
    fun createModel(realm: Realm): RealmObject 
} 

BaseProvider

open abstract class BaseProvider constructor(protected val context: Context?) : IDataProvider { 

    override fun execute(realm: Realm) { 
     realm.executeTransaction { r -> 
      createModel(r) 
     } 
    } 

    companion object { 
     fun create(context: Context?): IDataProvider { 
      if (something) { 
       return ChildProvider(context) 
      } else { 
       throw TypeNotSupportedException() 
      } 
     } 
    } 
} 

ChildProvider

class ChildProvider(context: Context?) : BaseProvider(context) { 
    override fun createModel(realm: Realm): ChildRealmModel { 
     var realmObject = realm.createObject(ChildRealmModel ::class.java) 
     //object property initialization 
     return realmObject 
    } 
} 

вызов UI

BaseProvider.create(context).execute(realm) 

Хотя метод createModel возвращает RealmObject, экземпляр будет иметь значение ChildRealmModel. Что мне не нравится в этом, так это то, что мы должны проверять тип экземпляра и вводить его, если нам нужна точная модель где-то в другом месте.

+0

Не могли бы вы уточнить, что вас не устраивает? Я не вижу, где вам нужно «проверять тип экземпляра и вводить его, если нам нужна точная модель». – voddan

ответ

1

Ваш код несовместим.

В объявлении функции вы обязуетесь вернуть E, что является подтипом BaseProvider<T> и может быть выбрано пользователем на сайте вызова.

Но в реализации вашего возвращения SomeChildProviderProvider, что, конечно, подтип BaseProvider<T>, но все еще может быть совершенно не связан с E который был выбран пользователем.

Пример:

class AnotherChildProvider : BaseProvider<ChildRealmModel>(context) {...} 

val x = BaseProvider.create<ChildRealmModel, AnotherChildProvider>(context) 

Что такое тип x? Согласно сигнатуре функции она должна быть AnotherChildProvider. Но внутри функции вы возвращаете SomeChildProviderProvider, который НЕ МОЖЕТ быть отличен до AnotherChildProviderProvider.

+0

Вы правы. Я устал, чтобы не понимать, что с помощью метода create я должен определить тип возвращающегося провайдера. Однако моя первоначальная идея состояла в том, чтобы иметь общий интерфейс. Провайдер реализует этот интерфейс и некоторый статический метод, где я могу решить, какой провайдер должен создать экземпляр. Мое решение находится в редакторе UPDATE 1 в редактируемом вопросе, но я все еще не доволен этим. – bajicdusko

 Смежные вопросы

  • Нет связанных вопросов^_^