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

msr*_*rd0 5 java delegates delegation kotlin

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

class MyClass(val delegate : MyInterface) : MyInterface
{
    override fun myAbstractFun1() = delegate.myAbstractFun1()
    override fun myAbstractFun2() = delegate.myAbstractFun2()
    // ...
}
Run Code Online (Sandbox Code Playgroud)

相反,我们可以编写以下代码,它们应该这样做:

class MyClass(val delegate : MyInterface) : MyInterface by delegate
Run Code Online (Sandbox Code Playgroud)

现在,我想delegate成为一个可变变量,即我的代码如下所示:

var delegate : MyInterface = MyImplementation()
object MyObject : MyInterface by delegate
Run Code Online (Sandbox Code Playgroud)

因此,如果我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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Nic*_*lla 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
Run Code Online (Sandbox Code Playgroud)

希望这仍然有用。