如何将实现委托给Kotlin中的可变属性?

时间:2018-01-01 23:29:48

标签: java delegates kotlin delegation

至于我的理解,在Kotlin中委托实现的想法是避免看起来像这样的代码:

class MyClass(val delegate : MyInterface) : MyInterface
{
    override fun myAbstractFun1() = delegate.myAbstractFun1()
    override fun myAbstractFun2() = delegate.myAbstractFun2()
    // ...
}

相反,我们可以编写以下代码:

class MyClass(val delegate : MyInterface) : MyInterface by delegate

现在,我希望delegate是一个可变变量,即我的代码如下:

var delegate : MyInterface = MyImplementation()
object MyObject : MyInterface by delegate

因此,如果我像第一个示例一样将自己的每个抽象方法委托给delegate,那么更改delegate的值确实会改变方法的行为。但是,上面的代码编译为此Java代码:

public final class MyObject implements MyInterface {
    public static final MyObject INSTANCE;
    // $FF: synthetic field
    private final MyInterface $$delegate_0 = MyObjectKt.access$getDelegate$p();

    @NotNull
    public String myAbstractFun1() {
        return this.$$delegate_0.myAbstractFun1();
    }

    @NotNull
    public String myAbstractFun2() {
        return this.$$delegate_0.myAbstractFun2();
    }
}

很明显,Kotlin编译器决定在创建delegate到最终字段MyObject时将其复制,而不是仅仅使用$$delegate_0字段,当我更改时不会修改价值delegate

有没有更好的解决方案,而不是手动委派每个方法?

1 个答案:

答案 0 :(得分:1)

可悲的是,据我所知,无法通过更改原始属性内容来更改代理,您仍然可以通过以不可变的方式进行复制并执行类似操作对象:

interface MyInterface {
  fun foo():Int
}

data class MyClass(val delegate : MyInterface) : MyInterface by delegate

object ImplementationA: MyInterface { override fun foo() = 7 }
object ImplementationB: MyInterface { override fun foo() = 5 }

val objA = MyClass(ImplementationA)
println(objA.foo()) // returns 7

val objB = objA.copy(ImplementationB)
println(objB.foo()) // returns 5
println(objA.foo()) // still 7

希望这仍然有用。