Невозможно заменить 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
Как установить атрибут веса динамически из кода Котлина? почему SomeClass :: class – это KClass <SomeClass>, но this :: class – это KClass <out SomeClass> Счетчик приращений и декретов FireStore Transactions получает непоследовательный результат Кинжал 2: несколько записей с одним и тем же ключом Файл spring-configuration-metadata.json не генерируется в IntelliJ Idea для класса Kotlin @ConfigurationProperties Будет ли карта Kotlin mapTo () перезаписывать данные уже в массиве? Создайте общий наблюдаемый, который избегает множественного вызова Параметр типа reated Kotlin не может использоваться как параметр типа в теле функции Проверьте, является ли класс допустимым значением для KParameter Чем отличаются код A и код B в Котлине? Kotlin – Почему эта функция не подходит для рекурсии хвоста? Проблемы подтипа с дженериками в Котлине Требовать сбой с номерами с плавающей точкой Проблемы с Observable.zip Каковы варианты использования встроенных свойств Kotlin?