让我们说明我们与一个具体类有以下接口:
interface Foo {
fun getString():String
}
class FooImpl : Foo {
private val amber = "Hello Amber!"
override fun getString(): String {
return amber
}
override fun toString(): String {
return amber
}
}
class FooWrapper(foo: Foo): Foo by foo然后我们使用以下方法运行:
val fooImpl = FooImpl()
val fooWrap = FooWrapper(fooImpl)
println("${fooImpl.toString()} vs ${fooWrap.toString()}")
println("${fooImpl.getString()} vs ${fooWrap.getString()}")我们就会得到
Hello Amber! vs test.myapplication.FooWrapper@90db1fa
Hello Amber! vs Hello Amber!为什么.toString也没有被委派?
发布于 2022-03-14 22:39:42
摘自科特林博士,在这里我根据您的示例更改了名称:
FooWrapper的超级类型列表中的by-子句指示foo将存储在FooWrapper的对象中,编译器将生成--转发到foo的的所有方法。
本质意思是:“在接口中声明的所有都被转发”。您没有将toString (或其他方法)声明为接口的一部分,因此不会发生自动转发。
添加明确的引用来解决这一问题:
interface Foo {
fun getString():String
override fun toString(): String
}注意,您需要指定override。
发布于 2022-03-15 05:30:59
正如Kotlin 文档所描述的那样:
Foo超级类型列表中的by-子句指示foo将在内部存储在FooWrapper的对象中,编译器将生成转发到foo的Foo的所有方法。
它和java静态代理一样,在这个代理中我们必须实现所有的接口方法,但是在kotlin中,委托使它变得很好,我们只需要覆盖我们想要修改或代理的方法,另一个方法就会自动生成它。这使得我们的代码简单明了。
在android中,我们可以使用这个工具显示kotlin字节码,它将显示实际的类。
public final class FooWrapper implements Foo {
// $FF: synthetic field
private final Foo $$delegate_0;
public FooWrapper(@NotNull Foo foo) {
Intrinsics.checkParameterIsNotNull(foo, "foo");
super();
this.$$delegate_0 = foo;
}
@NotNull
public String getString() {
return this.$$delegate_0.getString();
}
}至于toString方法,它属于对象,而不是Foo,因此它不是由foo委派的。它调用默认的父对象toString方法。
//In the java Object
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}所以它会打印test.myapplication.FooWrapper@90db1fa
https://stackoverflow.com/questions/71474566
复制相似问题