2016-12-25 286 views
0

我正在尝试为领域对象构建一组提供程序。 下面是一个例子结构,我试图建立:Kotlin泛型继承 - 类型不匹配

接口:

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

基地provider类与类型化提供商实例伴侣功能:

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.我知道我可以把它交给E,但在我看来,在这种情况下不应该需要。也许我错过了很明显的东西,或者可能缺乏Kotlin的知识。

UPDATE1: 第一个答案之后,我们已经意识到,上面的代码并没有太大的意义,因为我们必须定义一个类返回供应商,并把它传递到创建方法。最初的想法是,创建方法返回一些类型,这是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