2016-12-25 11 views
0

私は領域オブジェクトのプロバイダのセットを構築しようとしています。ここ は、私が構築しようとした構成例である:コトルのジェネリック継承 - 型の不一致

インタフェース:型付きプロバイダのインスタンス化のためのコンパニオン機能付き

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.私はそれをEに投げ入れることができると知っていますが、私の意見では、このような状況では必要ないはずです。多分私はここで何かを明らかにしていないか、おそらくKotlinの知識が欠けているでしょう。

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コール

:ここで私は最初のアイデアをサポートするために行った変更は、

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

あなたはそうです。私は作成メソッドを使用して、返すプロバイダのタイプを定義する必要があることに気づかないほど疲れていました。しかし、私の最初のアイデアは汎用インターフェースを持つことでした。そのインタフェースを実装するプロバイダと、インスタンス化するプロバイダを決定できる静的メソッドを実装します。私の解決策は編集された質問のUPDATE 1ですが、私はまだそれに満足していません。 – bajicdusko

関連する問題