Jan*_*Jan 5 delegates interface kotlin
我想通过 kotlin 扩展一个具有良好委托功能的库,但我陷入了一个地方,我想将两个不同的接口委托给同一个 impl。问题是,这两个接口具有共同的方法(一个扩展了另一个)。
所以存在一个由和接口Base扩展的接口。而 a实现了和,实际上库中有很多类似的实现和接口。ExtendedBaseFoo1Foo1ImplFooExtendedBase
interface Base: {
fun doBase()
fun doBase2()
// .. lots of methods
fun doBaseN()
}
interface ExtendedBase: Base {
fun doExtended()
fun doExtended2()
// .. lots of methods
fun doExtendedN()
}
interface Foo1: Base {
fun doFoo1()
}
class Foo1Impl: Foo1, ExtendedBase {
// some impl for doBase, doExtended and doFoo1
}
interface Foo2: Base {
fun doFoo2()
}
class Foo2Impl: Foo2, ExtendedBase {
// ...
}
// ... lots of interfaces and impls
interface FooN: Base {
fun doFooN()
}
class FooNImpl: FooN, ExtendedBase {
// ...
}
Run Code Online (Sandbox Code Playgroud)
我想扩展这个库并创建我自己的接口来扩展以下内容的ExtendedBase功能Foo[1..N]:
interface FooBar1: Foo1 {
fun doFooBar1()
}
class FooBar1Impl<T>
constructor(impl: T): FooBar1, ExtendedBase by impl, Foo1 by impl
where T: Foo1, T: ExtendedBase
{
override fun doFooBar1() {
println("foobar1")
}
}
//.. a lot of other extensions like FooBar[2..N] that all extended the bases with the same logic
Run Code Online (Sandbox Code Playgroud)
这些扩展会抱怨inheriting multiple implementations of it因为两者Foo1和ExtendedBase扩展Base。但实际上它很容易决定,因为只有一种实现可以委托给:impl: T。
1. 多接口实现的语法(kotlin 中不存在)
如果有一个多接口实现的语法,可能会像这样:
class FooBar1Impl<T>
constructor(impl: T): FooBar1, (ExtendedBase, Foo1) by impl
where T: Foo1, T: ExtendedBase
{ /* ... */ }
Run Code Online (Sandbox Code Playgroud)
2.类型参数声明的继承(对于jvm来说不可能)
如果 jvm 可以的话,我们可以写这样的东西,但事实并非如此:
class FooBar1Impl<T>
constructor(impl: T): FooBar1, T by impl
where T: Foo1, T: ExtendedBase
{ /* ... */ }
Run Code Online (Sandbox Code Playgroud)
3. 几乎可能:可以扩展的基础对象(仍然有问题)
open class BaseExtension constructor(impl: Base) : Base by impl
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
class FooBar1Impl<T>
constructor(impl: T): BaseExtension(impl), FooBar1
where T: Base, T: ExtendedBase
Run Code Online (Sandbox Code Playgroud)
但在这里你可以看到被抑制的警告就是问题所在。
4. 决定默认impl的语法(kotlin中不存在)
class FooBar1Impl<T>
constructor(impl: T): FooBar1, [default] ExtendedBase by impl, Foo1 by impl
where T: Foo1, T: ExtendedBase { /* .. */ }
Run Code Online (Sandbox Code Playgroud)
是否有任何工作流程可以让我免于Base手动覆盖所有方法?或者任何其他解决方案可以使这种扩展成为可能?
想象一下Base有类似的100方法,我需要手动重写。
好吧,我想我现在可能已经找到了解决方案:
首先,我将创建一个基本扩展类结构,它将方法从 和 委托Base给BaseExtension同一个构造函数属性。我需要/想要取消对此的警告......
出现警告是因为 kotlin 无法看到超类方法都委托给了impl该实现将重写方法委托给的同一实现:
open class BaseExtension<in T: Base>
constructor(private val impl: T) : Base by impl
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
open class Extension<in T>
constructor(private val impl: T) : BaseExtension<T>(impl), ExtendedBase by impl
where T: Base, T: ExtendedBase {
}
Run Code Online (Sandbox Code Playgroud)
然后,对于每个显式扩展,我将对其进行子类化Extension并实现显式扩展的接口,如下所示:
interface FooBar1: Foo1 {
fun doFooBar1()
}
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
class FooBar1Impl<in T>
constructor(private val impl: T) : FooBar1, Extension<T>(impl), Foo1 by impl
where T: Base, T: ExtendedBase, T: Foo1
{
fun doFooBar() { /* .. */ }
}
Run Code Online (Sandbox Code Playgroud)
最后,这不是一个非常简洁的解决方案,但至少没有错误,而且我不必再次实现任何已经实现的方法。虽然这个警告仍然让我烦恼,但我看不到任何解决办法。
如果有人提出了不包含这些需要抑制的警告的解决方案,那就太好了。