委譲オブジェクトが Java のデフォルトメソッドをオーバーライド (final および sealed クラスの場合) またはオーバーライドする可能性がある (open および abstract クラスの場合) クラスのインスタンスである場合、委譲を報告します。

デザインでは、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 の新機能です