据我了解,类(class)代表团应该
allow object composition to achieve the same code reuse as inheritance. [wikipedia]
Kotlin 支持类委托(delegate),请注意以下 documentation 中的语句:
overrides work as you might expect: The compiler will use your override implementations instead of those in the delegate object.
考虑到这一点,请考虑以下最小示例:
interface A {
val v: String
fun printV() {
Logger.getLogger().info(Logger.APP, "A", v)
}
}
class AImpl : A {
override val v = "A"
}
class B(a: A) : A by a {
override val v: String = "B"
}
我预计
B(AImpl()).printV()
将打印 B
, 但是它会打印 A
,即它使用 AImpl
的默认实现.此外,如果我覆盖
printV()
B 中的方法使用 super
实现,即class B(a: A) : A by a {
override val v: String = "B"
override fun printV() {
super.printV()
}
}
我现在预计
B(AImpl()).printV()
将打印 A
, 但是这次它打印 B
.这似乎违反直觉。
你能对这种行为给出一个很好的解释吗?
最佳答案
这按预期工作。
I expected that B(AImpl()).printV() would print B, however instead it prints A, i.e. it uses the default implementation of AImpl.
总是想象类委托(delegate),因为您会自己将调用重定向到委托(delegate)类:
class B(private val a: A) : A {
override val v: String = "B"
override fun printV() {
a.printV()
}
}
这清楚地表明,对
printV
的调用刚刚委派给 a
v
的值是多少并不重要在类(class) B
.Moreover, if I override the printV() Method in B using the super implementation, i.e. I now expected that B(AImpl()).printV() would print A, however this time it prints B. This seems counterintuitive.
同样,想象一下委托(delegate)在内部是如何工作的:
class B(private val a: A) : A {
override val v: String = "B"
override fun printV() {
super.printV() // the super call than uses the overridden v
}
}
这清楚地表明,
a
不再涉及和printV
使用您的本地覆盖变量。更新 1(第二部分详述)
https://kotlinlang.org/docs/reference/delegation.html
The Delegation pattern has proven to be a good alternative to implementation inheritance
因此,您不能将委托(delegate)视为继承。它是委托(delegate)(在维基百科中查找委托(delegate)模式)
... and the compiler will generate all the methods of Base that forward to b.
因此,您的接口(interface)(
v
-property 和 printV
)的所有方法都刚刚生成并转发到委托(delegate)类。这里是类
B
的代码片段和反编译的代码,看看它是如何在内部工作的:class B(a: A) : A by a {
override val v: String = "B"
}
class C(a: A) : A by a {
override val v: String = "B"
override fun printV() {
super.printV()
}
}
public final class B implements A {
@NotNull
private final String v = "B";
public B(@NotNull A a) {
this.$$delegate_0 = a;
this.v = "B";
}
@NotNull
public String getV() { return this.v; }
public void printV() {
this.$$delegate_0.printV();
}
}
public final class C implements A {
@NotNull
private final String v = "B";
public C(@NotNull A a) {
this.$$delegate_0 = a;
}
@NotNull
public String getV() {
return this.v;
}
/*This more or less means super.printV() */
public void printV() { A.DefaultImpls.printV(this); }
}
关于kotlin - 使用 Kotlin 类委托(delegate)覆盖的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46885891/