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
, когда я пытаюсь его создать, хотя мне кажется, что ничего не изменилось, кроме синтаксиса. Не понимаю ли я, как интерфейсы работают в Котлине?
Ответы
Ответ 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
}