这按预期工作。
我希望 B(AImpl()).printV() 会打印 B,但实际上它是
打印 A,即它使用 AImpl 的默认实现。
总是想象类委托,因为您会自己将调用重定向到委托类:
class B(private val a: A) : A {
override val v: String = "B"
override fun printV() {
a.printV()
}
}
这清楚地表明,对printV 的调用只是委托给a,v 在类B 中的值并不重要。
此外,如果我使用 super 覆盖 B 中的 printV() 方法
实施,即
我现在预计 B(AImpl()).printV() 会打印 A,但是这个
打印 B 的时间。这似乎违反直觉。
再次想象一下委托在内部是如何工作的:
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
委托模式已被证明是一个很好的替代方案
实现继承
因此,您不能将委托视为继承。它是委托(在维基百科中查找委托模式)
...编译器会生成Base的所有方法转发给b。
所以你接口的所有方法(v-property 和printV)只是生成并转发到委托类。
这里是 B 类的代码 sn-ps 和反编译的代码,看看它内部是如何工作的:
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); }
}