Невозможно заменить SAM-конструктор лямбдой, когда первый аргумент – это класс с одним методом

Я озадачен конструкторами SAM, у меня есть этот класс Java:

public class TestSam<T> { public void observe(ZeroMethods zero, Observer<T> observer) { } public void observe(OneMethod one, Observer<T> observer) { } public void observe(TwoMethods two, Observer<T> observer) { } public interface Observer<T> { void onChanged(@Nullable T t); } public interface ZeroMethods { } public interface OneMethod { First getFirst(); } public interface TwoMethods { First getFirst(); Second getSecond(); } public interface First { } public interface Second { } } 

И этот код Котлина:

 fun testSam( test: TestSam<String>, zero: TestSam.ZeroMethods, one: TestSam.OneMethod, two: TestSam.TwoMethods ) { test.observe(zero) { println("onChanged $it") } // 1. compiles test.observe(zero, TestSam.Observer { println("onChanged $it") }) // 2. Redundant SAM-constructor test.observe(one) { println("onChanged $it") } // 3. doesn't compile test.observe({ one.first }) { println("onChanged $it") } // 4. compiles test.observe(one, TestSam.Observer { println("onChanged $it") }) // 5. compiles test.observe(two) { println("onChanged $it") } // 6. compiles test.observe(two, TestSam.Observer { println("onChanged $it") }) // 7. Redundant SAM-constructor } 

Какая сделка здесь? Почему Котлин не может определить 3. (и предоставляет специальный вариант 4.), но справляется со всеми другими случаями?


Обоснованием для этого кода является LiveData<T>.observe(LifecycleOwner owner, Observer<T> observer) в Android, где LifecycleOwner имеет один метод getLifecycle() .

Я нашел правило в компиляторе: если вызов Java-метода требует типов, которые являются SAM-интерфейсами, тогда вы можете заменить их lambdas (или функциями), но либо все такие параметры, либо ни один из них.

Итак, у вас есть метод: public void observe(OneMethod one, Observer<T> observer) . Оба параметра являются кандидатами SAM. Вы можете позвонить:
observer(object1, object2)
или:
observer(function1, function2)

но не :
observer(object1, function2)
а не :
observer(function1, object2)

Такое же поведение будет даже в случае 3 или более параметров. Причиной этого является технические трудности в дизайне компилятора.

Извините, если я не очень ясен, я не очень хорош на английском.

Intereting Posts
Ошибка «Расширение с именем» android «не существует» при добавлении проекта Kotlin в Android Функция Котлина с нулевым / ненулевым вводом, отображаемым на нулевой / ненулевой вывод Ошибка приложения при попытке доступа к другому действию Firestore позволяет загружать только один документ Mockito / Powermock не работает должным образом с Kotlin Как проверить функции расширения Kotlin? динамический dsl с использованием kotlin с поддержкой контента Intellij не включает зависимость gradle от пути к классам при запуске приложения Переплет в карту с типом KClass Как написать преобразование многократного использования для значения String to Enum в группе классов Enum? (Котлин) kapt не разрешает генерируемые протобуфом классы после использования Kotlin, мой проект случится, что java.lang.NoClassDefFoundError Смешанная Kotlin + Java с Maven, неразрешенная ссылка Хорошо ли использовать функцию запуска вместо возврата в Котлин? Можно ли удалить непроверенный бросок в Kotlin при использовании arrayOfNulls?