2017-08-24 3 views
0

時々、型は同じ名前の抽象プロパティを持つ2つのインターフェイスを実装すると宣言されますが、トップレベルの抽象スーパークラスを別のオブジェクトにサブクラス化すると、両方のスーパーインタフェースの抽象プロパティをオーバーライドするクラスは、サブクラスの型引数を使用するときにコンパイルできません。複数継承されたフィールドのプロパティタイプがオーバーライドされた抽象valのサブタイプではありません

生成インターフェイスと抽象クラス:

interface Actor : Type { 
    val login: Stub<String> 
    val posts: Config<String, BasePostsArgs> 
} 

interface SomeConflict : Type { 
    val posts: Config<String, BasePostsArgs> 
} 

abstract class BasePostsArgs(
    args: ArgBuilder = ArgBuilder.create<String, BasePostsArgs>()) 
    : ArgBuilder by args 

同じ名前を持つ2つのスーパ特性オーバーライド生成されたオブジェクトの例:

object Organization : Type, SomeConflict, Actor { 

    override val login: Stub<String> = stub() 

    override val posts: Config<String, Organization.PostsArgs> = configStub(PostsArgs()) 

    class PostsArgs(args: ArgBuilder = ArgBuilder.create<String, PostsArgs>()) 
    : BasePostsArgs(args) { 

    fun first(value: Int): PostsArgs = apply { addArg("size", value) } 
    fun since(value: Date): PostsArgs = apply { addArg("since", value) } 
    } 
} 

そしてAPIのインタフェース:

interface Type { 
    fun <T> stub(): Stub<T> = StubImpl<T, ArgBuilder>() 

    fun <T, A : ArgBuilder> configStub(argBuilder: A): Config<T, A> = StubConfigImpl(argBuilder) 
} 

interface Config<T, A : ArgBuilder> { 
    fun config(): A 
} 

interface ArgBuilder { 
    fun addArg(name: String, value: Any): ArgBuilder 
    fun <T> build(): Stub<T> 

    companion object { 
    fun <T, A: ArgBuilder> create(): ArgBuilder = InternalImplementation<T, A>() as A 
    } 
} 

異なるフィールドに多型を持たせるために

class OrgPostsQuery(
    amount: Int = 100, 
    from: Date = Date.from(Instant.now())) : Model<Organization> { 

    val posts by super.model.config() 
    .first(1000) 
    .since(from) 
    .build() 

} 

(そこ例でpostsのようなフィールドのList<T>するためのインタフェースの別個のセットがありますが、私は簡潔さのためにそれをアウト左)

:私はこのようにそれらを宣言することができますので、まだ別の引数を必要とするインタフェースを実装するタイプの

私は間違って何をしていますか?またはこれは不可能ですか?

答えて

1

汎用のvalを型引数のサブタイプでオーバーライドできるようにするには、out-projectionを使用する必要があります。

Config<String, BasePostsArgs>Config<String, out BasePostsArgs>を、両方のインターフェイスと抽象クラスで変更します。次に、BasePostArgsのサブタイプを使用することができます。ここで、BasePostArgsが必要です。

interface Actor : Type { 
    val posts: Config<String, out BasePostsArgs> 
} 

interface SomeConflict : Type { 
    val posts: Config<String, out BasePostsArgs> 
} 

object Organization : Type, SomeConflict, Actor { 
    override val posts: Config<String, Organization.PostsArgs> = configStub(PostsArgs()) 

    /* ... */ 
} 

あなたが得るエラーは、いくつかのタイプAが、そのタイプのパラメータに不変であるならば、という事実によって引き起こされるT1T2がで(同じタイプでない場合は、その後、A<T1>A<T2>は、互いのサブタイプされることはありませんあなたのケース、T1 := BasePostsArgsT2 := Organization.PostsArgs)。しかし、out - 投影を使用する場合、はT1のサブタイプがT2の場合、サブタイプはA<T2>になります。また、valを基本タイプのプロパティのサブタイプで上書きすることもできます(ただし、varでは機能しません)。

+0

Intellijはそれを示唆していましたが、私はそれを見逃してしまったのか分かりません –

関連する問題