当委托对象是重写(对于 finalsealed 类的情况)或可能重写(对于 openabstract 类的情况)Java 默认方法的类的实例时,报告委托。

根据设计,Kotlin 委托不会覆盖 Java 默认方法,这可能导致难以捉摸的错误,尤其是在继承层次结构很深的情况下。

示例:


// Base.java:
public interface Base {
  default void print() {
    System.out.println("Base");
  }
}

// BaseImpl.kt:
class BaseImpl : Base {
  override fun print() {
    println("BaseImpl")
  }
}

// Main.kt:
fun main() {
  val inherited = BaseImpl()
  val delegated = object : Base by inherited {}
  inherited.print() // Outputs: BaseImpl
  delegated.print() // Outputs: Base
}

开发者通常期望所有方法,包括在委托中重写的默认方法,都被转发。 相反,调用的是 Java 默认方法,这可能会导致意外的结果。

一种快速修复是通过将 Java 默认方法的实现委托给委托对象来重写这些方法。


// Main.kt:
fun main() {
  val inherited = BaseImpl()
  val delegated = object : Base by inherited {
    override fun print() {
      inherited.print()
    }
  }
  inherited.print() // 输出: BaseImpl
  delegated.print() // 输出: BaseImpl
}

另一种快速修复是通过显式地将 Java 默认方法的实现委托给超类来重写这些方法。


// Main.kt:
fun main() {
  val inherited = BaseImpl()
  val delegated = object : Base by inherited {
    override fun print() {
      super.print()
    }
  }
  inherited.print() // Outputs: BaseImpl
  delegated.print() // Outputs: Base
}

2025.1 的新功能