Как использовать функцию Java 8 метода по умолчанию в интерфейсе, написанном на Kotlin

У меня есть класс A в java и интерфейс B в Kotlin.

// kotlin
interface B {
    fun optional()
}
// java
class A implements B {
}

Я хочу написать метод по умолчанию (функция Java 8) в интерфейсе Kotlin (B) и хочу реализовать его в классе A. Как я могу этого добиться?

Заранее спасибо.

2 ответа

В Kotlin методы интерфейса с телами по умолчанию компилируются следующим образом:

// kotlin
interface B {
    fun optional() { println("B optional body") }
}

составлен примерно так:

public interface B {
   void optional();
   public static final class DefaultImpls {
      public static void optional(B $this) {
         System.out.println("B optional body");
      }
   }
}

Затем в классах Kotlin, реализующих этот интерфейс, компилятор добавляет переопределение для optional метод автоматически и вызывает B.DefaultImpls.optional(this) там.

public final class KA implements B {
   public void optional() {
      B.DefaultImpls.optional(this);
   }
}

Но что, если вы хотите реализовать этот интерфейс на Java и избежать необходимости переопределять optional метод и вызов B.DefaultImplsвручную? В этом случае вы можете использовать экспериментальный@JvmDefaultособенность.

Во-первых, вам нужно включить пару параметров компилятора:

  • Целевой байт-код JVM версии 1.8 или выше: -jvm-target 1.8
  • включить методы JVM по умолчанию: -Xjvm-default=enable (см. другие доступные значения параметров по ссылке выше)

Затем вы комментируете optional метод с @JvmDefault аннотация:

// kotlin
interface B {
    @JvmDefault
    fun optional() { println("B optional body") }
}

и он компилируется в

public interface B {
   @JvmDefault
   default void optional() {
      System.out.println("B optional body");
   }
}

И теперь Java-реализация этого интерфейса становится просто:

public final class A implements B {
}

Пока есть другие классы, кроме A реализация B, это может иметь смысл. В противном случае вам либо не нужна реализация по умолчанию, либо вам не нужно реализовывать этот метод в классе реализации.

Однако сделать это можно так:

interface B {
    fun optional() { print("optional") }
}

class A implements B {
    override fun optional() { print("B's optional") }
}
Другие вопросы по тегам