委譲オブジェクトが 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 の新機能です