【发布时间】:2018-06-11 18:06:09
【问题描述】:
据我了解,在 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 编译器决定在创建 MyObject 时将其复制到最终字段 $$delegate_0 中,而不是仅使用 delegate 字段,而当我更改 delegate 的值时,该字段不会被修改
有没有更好的解决方案来代替手动委派每个方法?
【问题讨论】:
-
这个的用例是什么?
-
@Todd 我正在尝试拥有一个全局对象来保存我的库的配置以及提供修改它的方法。我知道有不同的方法可以实现这一点,但这似乎是一种方便的方式,可以在一个地方拥有属性和方法,而无需创建包装类
-
如果通过正确的
object,它甚至不起作用!看来编译器真的非常想知道静态会发生什么。我认为这也有道理;如果你自己实现了这些方法,它们在运行时不会改变(除非反射),所以为了有类似的保证,编译器需要修复委托。 -
@Raphael 我不明白这有什么意义,因为当实例变量发生变化时,手动实现的方法可以改变 bedaviour。那么为什么自动生成的方法不应该也是这样呢?
标签: java delegates kotlin delegation