Котлин: интерфейс ... не имеет конструкторов
Я конвертирую некоторые из моих Java-кода в Kotlin, и я не совсем понимаю, как создавать экземпляры интерфейсов, которые определены в коде Kotlin. В качестве примера, у меня есть интерфейс (определенный в коде Java):
public interface MyInterface {
void onLocationMeasured(Location location);
}
а затем далее в моем коде Kotlin я создаю этот интерфейс:
val myObj = new MyInterface { Log.d("...", "...") }
и он отлично работает. Однако, когда я конвертирую свой интерфейс в Kotlin:
interface MyInterface {
fun onLocationMeasured(location: Location)
}
Я получаю сообщение об ошибке: Interface MyListener does not have constructors когда я пытаюсь создать его экземпляр, хотя это мне кажется, что ничего не изменилось, кроме синтаксиса. Я неправильно понимаю, как работают интерфейсы в Котлине?
4 ответов:
ваш код Java основан на преобразовании SAM - автоматическом преобразовании лямбды в интерфейс с помощью одного абстрактного метода. Сэм преобразование в настоящее время не поддерживается для интерфейсов, определенных в Kotlin. Вместо этого необходимо определить анонимный объект, реализующий интерфейс:
val obj = object : MyInterface { override fun onLocationMeasured(location: Location) { ... } }
лучшее решение-использовать typealias вместо вашего интерфейса Java
typealias MyInterface = (Location) -> Unitfun addLocationHandler(myInterface:MyInterface) { }зарегистрируйте его следующим образом:
val myObject = { location -> ...} addLocationHandler(myObject)или еще лучше
addLocationHandler { location -> ...}вызовите его так:
myInterface.invoke(location)все 3 варианта могут быть:
- typealias (грязный при вызове с java)
- интерфейс kotlin (грязный при вызове из kotlin; вам нужно создать объект) это большой шаг назад ИМО.
- интерфейс java (менее грязный при вызове из kotlin; лямбда-имя интерфейса должно быть добавлено, поэтому вам не нужен объект; также нельзя использовать лямбда вне соглашения о скобках функций)
при преобразовании наших библиотек в Kotlin мы фактически оставили все интерфейсы в Java-коде, так как было чище вызывать Java из Kotlin, чем Kotlin из Kotlin.
если у вас Java-класс такой :
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new RecyclerTouchListener.ClickListener() { //Your Code }));вы должны преобразовать этот код из Java в Котлин такой :
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()до Котлин Интерфейс стиль:
object : RecyclerTouchListener.ClickListener
попробуйте получить доступ к вашему интерфейсу следующим образом:
object : MyInterface { override fun onSomething() { ... } }
Comments