As to my understanding, the idea of delegating an implementation in Kotlin is to avoid code that looks like this:
class MyClass(val delegate : MyInterface) : MyInterface
{
override fun myAbstractFun1() = delegate.myAbstractFun1()
override fun myAbstractFun2() = delegate.myAbstractFun2()
// ...
}
Instead, we can write the following code which should do the same:
class MyClass(val delegate : MyInterface) : MyInterface by delegate
Now, I'd like delegate
to be a mutable variable, i.e. my code looks like this:
var delegate : MyInterface = MyImplementation()
object MyObject : MyInterface by delegate
So if I'd delegated every abstract method to delegate
by myself like in the first example, changing the value of delegate
does change the behaviour of the methods. However, the above code compiles to this Java code:
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();
}
}
So obviously, instead of just using the delegate
field, the Kotlin compiler decides to copy it when creating MyObject
to a final field $$delegate_0
, which is not modified when I change the value of delegate
Is there a better solution for doing this instead of delegating every method manually?
object
! It seems the compiler really, really want to know statically what's going to happen. I think that makes sense, too; if you implemented the methods yourself, they wouldn't change at runtime (unless reflection), so in order to have similar guarantees, the compiler needs to fix the delegate. – Violaviolableval
won't change). If you swap out the delegate -- potentially with a whole different class! -- what is declared as aval
(in the delegate interface) suddenly changed. (Note how you could never ever delegateval
s!) Therefore, if you allowed to swap out delegate objects, the compiler can rely on (far?) fewer things. Now, that doesn't imply one couldn't allow that; it's probably a trade-off. – Violaviolable