Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 使用类委托时,是否有方法重写委托对象的方法使用的成员?_Kotlin - Fatal编程技术网

Kotlin 使用类委托时,是否有方法重写委托对象的方法使用的成员?

Kotlin 使用类委托时,是否有方法重写委托对象的方法使用的成员?,kotlin,Kotlin,在Kotlin中使用类委托时,可以重写成员。然而,报告说: 但是,请注意,以这种方式重写的成员不会从委托对象的成员调用,委托对象只能访问其自己的接口成员实现 我希望重写委托对象的方法使用的属性,以便委托对象的方法调用此重写属性。正如文档所述,用override关键字覆盖属性并不能实现这一点。有什么方法可以让我实现这种行为吗?如果不是,这是否表明我应该改用继承 下面是一个代码示例: interface Base { val message: String fun print() }

在Kotlin中使用类委托时,可以重写成员。然而,报告说:

但是,请注意,以这种方式重写的成员不会从委托对象的成员调用,委托对象只能访问其自己的接口成员实现

我希望重写委托对象的方法使用的属性,以便委托对象的方法调用此重写属性。正如文档所述,用
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()
}