这不是使用 Kotlins class 委托引用原始对象
This not referring to the original object using Kotlins class delegation
我对委托在 Kotlin 中的工作方式感到困惑。 Wikipedia 说:
With language-level support for delegation, this is done implicitly by having self in the delegate refer to the original (sending) object, not the delegate (receiving object).
给定以下代码:
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
我希望委托给 return Delegated
因为 self/this 应该引用原始对象。是我理解错了还是 Kotlin 委托不同?
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
.
我认为如果我们查看编译成的反编译 Java 字节码,这最容易理解:
You can do this by going to Tools > Kotlin > Show Kotlin Bytecode
and then clicking 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 class 将在 $$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。
我对委托在 Kotlin 中的工作方式感到困惑。 Wikipedia 说:
With language-level support for delegation, this is done implicitly by having self in the delegate refer to the original (sending) object, not the delegate (receiving object).
给定以下代码:
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
我希望委托给 return Delegated
因为 self/this 应该引用原始对象。是我理解错了还是 Kotlin 委托不同?
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
.
我认为如果我们查看编译成的反编译 Java 字节码,这最容易理解:
You can do this by going to
Tools > Kotlin > Show Kotlin Bytecode
and then clickingDecompile
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 class 将在 $$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。