Переопределение нескольких методов интерфейса в лямбда-выражениях Котлина

Скажем, у меня есть интерфейс Callbacks с двумя методами onCurrentLocation и onError :

  public interface Callbacks { void onCurrentLocation(ClientLocation location); void onError(); } 

и класс, который принимает этот интерфейс в своем конструкторе, скажем:

 public MyLocationClient(Callbacks callbacks) {...} 

Теперь, в Котлине, должен ли я создать экземпляр MyLocationClient следующим образом:

 val myLocationClient = MyLocationClient( { location: ClientLocation -> updateClientLocation(location) }, {}) 

И если нет, то почему?

Поведение, которое я вижу, следующее: когда интерфейс имеет только один метод, построение этого объекта компилируется отлично. Но, как только я добавляю больше методов для Callbacks , компилятор жалуется

Msgstr "Неисправность типа. Обязательно: Обратные вызовы! Найдено: (ClientLocation) -> Единица"

Изменить: удалил нулевую проверку location так как это не имело значения для вопроса.

Я думаю, это хорошо, что это не работает, потому что что вы делаете, когда интерфейс имеет две функции одного типа?

 public interface Callbacks { void anotherFunction(ClientLocation location); void onCurrentLocation(ClientLocation location); } 

Поэтому ограничение этого на SAM (один абстрактный метод) – это хороший подход, который я бы сказал.

Таким образом, вы создаете экземпляр в анонимном классе, который не является функциональным интерфейсом (у них есть только один метод), поэтому это будет что-то вроде:

 val myLocationClient = MyLocationClient(object : Callbacks { override fun onCurrentLocation(location : ClientLocation?){ location?.let{ updateLocation(it) } } override fun onError(){ // should you not handle errors? } }) 

Вы можете определить

 class CallbacksImpl(private val onCurrentLocationF: (ClientLocation) -> Unit, private val onErrorF: () -> Unit) : Callbacks { override fun onCurrentLocation(location : ClientLocation) { onCurrentLocationF(location) } override fun onError() { onErrorF() } } 

и использовать его

 MyLocationClient(CallbacksImpl( { location -> updateClientLocation(location) }, {})) 

Он по-прежнему имеет некоторый шаблон, но один раз за интерфейс, а не один раз за использование, поэтому он может легко быть хорошим компромиссом.

 interface IAnimatedRatingBar { fun setProgressImageResource(resourceId: Int) fun setProgressImageDrawable(drawable: Drawable) fun setSecondaryProgressImageResource(resourceId: Int) fun setSecondaryProgressImageDrawable(drawable: Drawable) fun startAnimate() } 

Это отлично работает для меня.

Intereting Posts
Как создать неизменяемый список, который должен пересекать поле другого списка Как создать кеширование / горячую версию rx.Single? Ресивер RecyclerView вызывается самостоятельно Intellij IDEA отладчик не работает над проектом Gradle Vert.X Резервный SAM-конструктор нельзя удалить для объявленной функции Kotlin, но работает над объявленной Java-функцией Android всех видов ошибок от Gradle и Kotlin Предупреждение и выход из системы Kotlin / Quasar Fiber Как сделать компиляциюKotlin dependsOn compileJava в gradle версия kotlin, которая используется для построения с градиентом (1.1.2-5), отличается от той, что включена в плагин IDE (1.1.2-4) Могу ли я обновить глубоко вложенный неизменный объект, не сообщая ему о его контексте? Неразрешенная ссылка: привязка данных Почему я не могу получить доступ к переименованию суперкласса в Котлине? Gradle kotlin-spring плагин не открывает весенние классы Простой способ отображения моделей данных в модели домена Kapt3: java.io.File не может быть добавлен в java.lang.String