Kotlin 使用类委托时,是否有方法重写委托对象的方法使用的成员?
在Kotlin中使用类委托时,可以重写成员。然而,报告说: 但是,请注意,以这种方式重写的成员不会从委托对象的成员调用,委托对象只能访问其自己的接口成员实现 我希望重写委托对象的方法使用的属性,以便委托对象的方法调用此重写属性。正如文档所述,用Kotlin 使用类委托时,是否有方法重写委托对象的方法使用的成员?,kotlin,Kotlin,在Kotlin中使用类委托时,可以重写成员。然而,报告说: 但是,请注意,以这种方式重写的成员不会从委托对象的成员调用,委托对象只能访问其自己的接口成员实现 我希望重写委托对象的方法使用的属性,以便委托对象的方法调用此重写属性。正如文档所述,用override关键字覆盖属性并不能实现这一点。有什么方法可以让我实现这种行为吗?如果不是,这是否表明我应该改用继承 下面是一个代码示例: interface Base { val message: String fun print() }
override
关键字覆盖属性并不能实现这一点。有什么方法可以让我实现这种行为吗?如果不是,这是否表明我应该改用继承
下面是一个代码示例:
interface Base {
val message: String
fun print()
}
class BaseImpl(val x: Int) : Base {
override val message = "BaseImpl: x = $x"
override fun print() { println(message) }
}
class Derived(b: Base) : Base by b {
// This property is not accessed from b's implementation of `print`
override val message = "Message of Derived"
}
fun main(args: Array<String>) {
val b = BaseImpl(10)
val derived = Derived(b)
derived.print()
}
接口基础{
val消息:字符串
趣味印刷品()
}
类BaseImpl(val x:Int):基{
覆盖val message=“BaseImpl:x=$x”
覆盖趣味打印(){println(消息)}
}
派生类(b:Base):由b派生的Base{
//无法从b的“print”实现访问此属性`
override val message=“派生的消息”
}
趣味主线(args:Array){
val b=基本输入(10)
val派生=派生(b)
派生的
}
此代码打印“BaseImpl:x=10”,但我希望它打印“派生消息”。问题在于生成的代码:
public final class BaseImpl implements Base {
@NotNull
private final String message;
private final int x;
@NotNull
public String getMessage() {
return this.message;
}
public void print() {
String var1 = this.getMessage();
System.out.println(var1);
}
public final int getX() {
return this.x;
}
public BaseImpl(int x) {
this.x = x;
this.message = "BaseImpl: x = " + this.x;
}
}
public interface Base {
@NotNull
String getMessage();
void print();
}
public final class Derived implements Base {
@NotNull
private final String message;
// $FF: synthetic field
private final Base $$delegate_0;
@NotNull
public String getMessage() {
return this.message;
}
public Derived(@NotNull Base b) {
Intrinsics.checkParameterIsNotNull(b, "b");
super();
this.$$delegate_0 = b;
this.message = "Message of Derived";
}
public void print() {
this.$$delegate_0.print();
}
}
我花了一段时间才发现,但要点如下:
委派并不意味着扩展特定类型;这意味着重写基(在本例中)接口,并将未覆盖的事件发送到委托类。这里有两件事需要密切关注:
public void print() {
this.$$delegate_0.print();
}
public final class Derived extends BaseImpl {
@NotNull
private final String message = "Message of Derived";
@NotNull
public String getMessage() {
return this.message;
}
public Derived(int x) {
super(x);
}
}
及
这是什么意思?这意味着Derived
不会以任何方式覆盖BaseImpl
。为了说明我的意思,请使用以下代码:
interface Base {
val message: String
fun print()
}
open class BaseImpl(val x: Int) : Base { // This needs to be `open` to override
override val message = "BaseImpl: x = $x"
override fun print() { println(message) }
}
class Derived(x: Int) : BaseImpl(x) {
// This property is not accessed from b's implementation of `print`
override val message = "Message of Derived"
}
fun main(args: Array<String>) {
val derived = Derived(10)
derived.print()
}
您可能会看到打印方法已不复存在;这是因为您没有覆盖它。此外,它现在扩展了BaseImpl,而不是实现了Base
。对getMessage
方法的任何调用(您可以看到在print方法中调用了该方法)都将“重定向”到被重写的方法,而不是基类中的方法
如果您在Java中这样做,而不是使用getter直接调用字段,那么它将不起作用,因为。它在Kotlin开箱即用中工作的原因是,正如您在反编译代码中看到的,它使用方法
你想如何解决这个问题取决于你自己。如果仍要使用委托属性,则需要重写派生类中的print方法。因为,正如我前面提到的,Derived
和BaseImpl
之间没有实际的关系,只有一个共享的父级。但是Derived
不是BaseImpl
的子代
因此,覆盖前面提到的getMessage()
将不起作用。另外,通过执行override val message=…
可以生成一个覆盖getter,如我的第二个示例所示
TL;DR:Base by b
实现Base,并向委派的BaseImpl
发送对print
的调用Derived
不是BaseImpl
的子级,因此,BaseImpl
无法在Derived
中调用getMessage()
getter,因此打印自己的消息
interface BaseInterface {
fun doSomething()
fun doSomethingElse()
}
class BaseImpl : BaseInterface {
override fun doSomething() = println("doSomething in BaseImpl")
override fun doSomethingElse() = println("doSomethingElse in BaseImpl")
}
class Derived : BaseInterface by BaseImpl() {
override fun doSomething() = println("doSomething in Derived")
}
fun main() {
val obj = Derived()
obj.doSomething()
obj.doSomethingElse()
}
衍生产品中的剂量测定
BaseImpl中的doSomethingElse我认为您需要使用override fun getMessage()
interface BaseInterface {
fun doSomething()
fun doSomethingElse()
}
class BaseImpl : BaseInterface {
override fun doSomething() = println("doSomething in BaseImpl")
override fun doSomethingElse() = println("doSomethingElse in BaseImpl")
}
class Derived : BaseInterface by BaseImpl() {
override fun doSomething() = println("doSomething in Derived")
}
fun main() {
val obj = Derived()
obj.doSomething()
obj.doSomethingElse()
}