Как реализовать этот интерфейс Java в Kotlin?

Поскольку у Kotlin нет примитивов, как реализовать этот интерфейс?

public interface A {
  @NotNull Object get(@NotNull Integer i);
  @NotNull Object get(int i);
}

Я не могу изменить код Java, так как это скомпилированный файл класса в двоичной библиотеке.

5 ответов

Решение

Если одной реализации, как в zsmb13, вам недостаточно, и вам нужны отдельные реализации для двух методов в Kotlin, то вы можете добавить промежуточный интерфейс, переопределяющий метод, принимающий Integer с обнуляемым параметром:

private interface IntermediateA : A {
    override fun get(i: Int?): Any
}

Реализация этого интерфейса вместо оригинального Aкомпилятор Kotlin будет различать два метода, что позволит вам переопределить их следующим образом:

class C : IntermediateA {
    override fun get(i: Int) = "primitive"
    override fun get(i: Int?) = "boxed"
}

val a: A = C()
println(a.get(1)) // primitive
println(a.get(1 as Int?)) // boxed

Если у вас был доступ к коду Java, вы могли бы это исправить, добавив аннотацию обнуляемости в метод, принимающий упакованный тип:

Object get(@Nullable Integer i);

Компилятор Kotlin понимает различные виды аннотаций обнуляемости, вот список.

Реализация только одного метода, который занимает Int как его параметр работает, и может быть вызван из Kotlin или Java.

class B : A {

    override fun get(i: Int): Any {
        return "something"
    }

}

Если вы декомпилируете байт-код, вы увидите, что компилятор Kotlin достаточно умен для создания обоих методов, причем один из них просто перенаправляет на реальную реализацию.

Пример декомпилированного байт-кода

Одной из возможных проблем является то, что вы не можете заставить метод принять Int?, и он потерпит крах с NullPointerException на .intValue() вызовите, если он вызывается из Java следующим образом:

B b = new B();
Integer i = null;
b.get(i);

Я не уверен, есть ли способ решить для этого варианта использования.

Изменить: ответ горячей клавиши содержит остальные ответы.

В Котлине мы можем заявить:

  • примитив int как: Int
  • упакованный как: Int?

Ваш интерфейс может быть упрощен до:

private interface ModifiedA : A {
    override fun get(i: Int?): Any
}

В Kotlin, если вы реализуете этот измененный интерфейс, Kotlin предоставит вам два метода для переопределения. Один для примитивного типа, а другой для коробочного типа.

class ImplementationOfA : ModifiedA {
    override fun get(i: Int)
    override fun get(i: Int?)
}

Я пишу простую демонстрацию на Java.

затем конвертируйте его в Kotlin с помощью плагинов Kotlin в IntelliJ IDEA или Android Studio.

добавьте эти строки для реализации интерфейса в kotlin

      class abc : AppCompatActivity(), interface 1, interface 2,
{
override fun get(i: Int?): Any
}
Другие вопросы по тегам