这不是使用Kotlins类委托引用原始对象

时间:2018-10-11 21:12:29

标签: kotlin delegation

我很困惑代表团在科特林的工作方式。 Wikipedia说:

  

有了语言级的委派支持,这可以通过使委托中的self引用原始(发送)对象而不是委托(接收对象)来隐式完成。

给出以下代码:

interface BaseInterface {
    fun print()
}

open class Base() : BaseInterface {
    override fun print() { println(this) }
}

class Forwarded()  {
    private val base = Base()

    fun print() { base.print() }
}

class Inherited() : Base() {}

class Delegated(delegate: BaseInterface) : BaseInterface by delegate

fun main(args: Array<String>) {
    print("Forwarded: ")
    Forwarded().print();
    print("Inherited: ")
    Inherited().print();
    print("Delegated: ")
    Delegated(Base()).print();
}

我得到以下输出:

Forwarded: Base@7440e464
Inherited: Inherited@49476842
Delegated: Base@78308db1

我希望Delegated返回Delegated,因为self / this应该引用原始对象。我会弄错还是科特林斯代表团不同?

2 个答案:

答案 0 :(得分:0)

Kotlin delegation非常简单-它生成所有接口方法,并在委托对象上隐式调用它,但用户显式覆盖的方法除外。

您的示例与以下功能相同:

class Delegated(delegate: BaseInterface) : BaseInterface{
    // when generating bytecode kotlin assigns delegate object to internal final variable
    // that is not visible at compile time
    private val d = delegate

    override fun print(){
        d.print()
    }
}

因此,很清楚为什么打印Base

答案 1 :(得分:0)

如果我们查看将其反编译成的反编译后的Java字节码,我认为这是最容易理解的

  

您可以执行以下操作:转到Tools > Kotlin > Show Kotlin Bytecode,然后单击Decompile

public final class Delegated implements BaseInterface {
   // $FF: synthetic field
   private final BaseInterface $$delegate_0;

   public Delegated(@NotNull BaseInterface delegate) {
      Intrinsics.checkParameterIsNotNull(delegate, "delegate");
      super();
      this.$$delegate_0 = delegate;
   }

   public void print() {
      this.$$delegate_0.print();
   }
}

因此,当您进行接口委托时,会发生的事情是Kotlin为名为$$delegate_0的委托创建了一个字段,并在您的 delegating 类中添加了将在其上运行的方法。 $$delegate_0。您也可以有多个代表,他们将获得自己的字段。但是有一个警告:您不能直接访问$$delegate_0,即使您将其设置为var也是如此:

class Delegated(var delegate: BaseInterface) : BaseInterface by delegate

它将编译为:

public final class Delegated implements BaseInterface {
   @NotNull
   private BaseInterface delegate;
   // $FF: synthetic field
   private final BaseInterface $$delegate_0;

   @NotNull
   public final BaseInterface getDelegate() {
      return this.delegate;
   }

   public final void setDelegate(@NotNull BaseInterface var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.delegate = var1;
   }

   public Delegated(@NotNull BaseInterface delegate) {
      Intrinsics.checkParameterIsNotNull(delegate, "delegate");
      super();
      this.$$delegate_0 = delegate;
      this.delegate = delegate;
   }

   public void print() {
      this.$$delegate_0.print();
   }
}

可悲。我已经写过有关here的话题。