2016-12-25 287 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