위임 객체가 Java 디폴트 메서드를 재정의하는 클래스(finalsealed 클래스)의 인스턴스이거나 재정의할 수 있는 클래스(openabstract 클래스)의 인스턴스인 경우 위임을 보고합니다.

이러한 재정의는 특히 상속 계층 구조가 깊은 경우에 까다로운 버그를 일으킬 수 있어 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의 새로운 기능