Подтвердить что ты не робот

Kotlin: Интерфейс... не имеет конструкторов

Я конвертирую часть своего кода Java в Kotlin, и я не совсем понимаю, как создавать интерфейсы, определенные в коде Kotlin. В качестве примера у меня есть интерфейс (определенный в Java-коде):

public interface MyInterface {
    void onLocationMeasured(Location location);
}

И далее в моем коде Kotlin я создаю экземпляр этого интерфейса:

val myObj = new MyInterface { Log.d("...", "...") }

и он отлично работает. Однако, когда я конвертирую MyInterface в Kotlin:

interface MyInterface {
    fun onLocationMeasured(location: Location)
}

Я получаю сообщение об ошибке: Interface MyListener does not have constructors, когда я пытаюсь его создать, хотя мне кажется, что ничего не изменилось, кроме синтаксиса. Не понимаю ли я, как интерфейсы работают в Котлине?

4b9b3361

Ответ 1

Ваш код Java основан на преобразовании SAM - автоматическое преобразование лямбда в интерфейс с помощью одного абстрактного метода. Преобразование SAM в настоящее время не поддерживается для интерфейсов, определенных в Kotlin. Вместо этого вам нужно определить анонимный объект, реализующий интерфейс:

val obj = object : MyInterface {
    override fun onLocationMeasured(location: Location) { ... }
}

Ответ 2

Лучшим решением является использование typealias на месте вашего интерфейса Java

typealias MyInterface = (Location) -> Unit

fun addLocationHandler(myInterface:MyInterface) {

}

Зарегистрируйте его следующим образом:

val myObject = { location -> ...}
addLocationHandler(myObject)

или даже более чистый

addLocationHandler { location -> ...}

Вызвать это следующим образом:

myInterface.invoke(location)

Возможны 3 текущих варианта:

  • typealias (беспорядочный при вызове из java)
  • интерфейс kotlin (беспорядочный при вызове из kotlin; вам нужно создать объект). Это большой шаг назад IMO.
  • java-интерфейс (менее беспорядочный при вызове из kotlin; lambda требует имя интерфейса, добавленное, чтобы вам не нужен объект, также не может использовать лямбда вне соглашения о скобках функций)

При конвертировании наших библиотек в Kotlin мы фактически оставили все интерфейсы в Java-коде, так как было чище называть Java от Kotlin, а не Kotlin от Kotlin.

Ответ 3

если у вас есть класс Java, например:

recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new RecyclerTouchListener.ClickListener()
        {
              //Your Code
        }));

вы должны преобразовать этот код из Java в Kotlin следующим образом:

override fun showJozList (list : List<ResponseGetJuzList.Parameter4>) {
        adapter.addData(list)
        jozlist_recycler.addOnItemTouchListener(RecyclerTouchListener(
                activity ,
                jozlist_recycler ,
                object : RecyclerTouchListener.ClickListener
                    {
                          //Your Code
                    }))

конвертировать интерфейс Java :

new RecyclerTouchListener.ClickListener()

- Интерфейс Kotlin Стиль:

object : RecyclerTouchListener.ClickListener

Ответ 4

Попробуйте получить доступ к вашему интерфейсу следующим образом:

 object : MyInterface {
    override fun onSomething() { ... }
}

Ответ 5

Если интерфейс предназначен для метода прослушивателя класса, измените определение интерфейса на тип функции. Это делает код более лаконичным. Смотрите следующее.

Класс, содержащий определение слушателя

// A class
private var mLocationMeasuredListener = (location: Location) -> Unit = {}

var setOnLocationMeasuredListener(listener: (location: Location) -> Unit) {
    mLocationMeasuredListener = listener
}

// somewhere in A class
mLocationMeasuredListener(location)

Другой класс

// B class
aClass.setOnLocationMeasuredListener { location ->
    // your code
}