Ссылки функций и лямбда

Я сталкиваюсь с ошибкой компиляции при попытке использовать ссылки lambdas / function с kotlin:

class Foo { fun getFilteredList(){ val numbers = listOf(1, 2, 3) numbers.filter(::isOdd) // prints [1, 3] } fun isOdd(x: Int): Boolean = x % 2 != 0 } 

Но я получаю ошибку времени компиляции, говоря о несоответствии типа:

Ошибка: (18, 16) Gradle: Ошибка ввода типа: inline fun kotlin.Iterable.filter (предикат: (T) -> kotlin.Boolean): kotlin.List нельзя применить к получателю: kotlin.List аргументы: (kotlin. reflect.KFunction2) Ошибка: (18, 23) Gradle: Тип несоответствия: выведенный тип kotlin.reflect.KFunction2 but (kotlin.Int) -> ??? (18, 23) Gradle: Тип несоответствия: выводный тип – kotlin.reflect.KFunction2, но (kotlin.Int) -> kotlin.Boolean ожидалось Ошибка: (18, 25) Gradle: Левая часть вызываемая ссылка с параметром приемника не может быть пустым. Укажите тип приемника до «::» явно

Я не уверен, что такое ошибка, и какой тип я должен явно указывать перед '::'

Другой вопрос: могу ли я использовать другую функцию объектов в качестве ссылки в котлин? Что-то вроде этого:

 class Bar { fun isOdd(x: Int): Boolean = x % 2 != 0 } class Foo { fun getFilteredList(){ val bar = Bar() val numbers = listOf(1, 2, 3) numbers.filter(bar::isOdd) // Use Bar's method } } 

Во втором примере: да, опорный синтаксис связанной функции поддерживается с Kotlin 1.1, поэтому вы можете написать bar::isOdd аналогично Java.

В первом примере ошибка пытается сказать, что isOdd на самом деле является функцией двух параметров (типов Foo и Int ), а передача функции, принимающей два параметра в качестве аргумента, тип которого является функцией одного параметра, недопустима. Чтобы сделать пример компиляции, вы можете сделать isOdd верхней или локальной функцией, которая сделает ее функцией одного параметра типа Int . Или, если вы используете Kotlin 1.1+, используйте ссылочный синтаксис связанной функции и просто напишите this::isOdd .

Забавно. «Java ударяет». ха-ха

Ваша проблема проста: вы объявили isOdd в классе Foo , правильно? Тогда это не функция , а метод . Это означает, что для этого требуется экземпляр Foo ( this ссылка), поэтому он является функцией из двух параметров: Foo.(Int) -> Boolean . И синтаксическая ошибка показывает, что ссылка на метод выглядит как Foo::isOdd .

В любом случае, объявление нестатического метода, который не использует объект, является антипаттерном даже в Java, не согласны ли вы?

Проблема может быть решена путем объявления свободной функции без класса или путем ее расширения: fun Int.isOdd()

PS Что касается второго вопроса – эта функция еще не поддерживается.

Intereting Posts
Приложение Android на Gradle: невозможно слить dex Локальные функции доступа к родительским переменным с тем же именем Как использовать настраиваемый сеттер в корпусе конструктора класса Kotlin Android Kotlin – Не удается вызвать onNavigationItemSelected метод Мое собственное решение для отсутствия пробных ресурсов Котлина Spring Data Neo4j – ORDER BY {order} не работает Доступность собственности в Котлине Ошибка: ошибка: разрешены только безопасные (?.) Или непустые (!!.) Вызовы в приемнике с нулевым значением типа View? Robolectric addResolveInfoForIntent не работает Как получить имена параметров через отражение в котлин? В чем причина «неразрешенной ссылки» при использовании kotlin для FacebookLogin? Как получить класс Any val Почему Котлин не выполняет автоматическое литье под давлением? Котлин Поэт пустой генерации конструктора – наследование Kolin – Список элементов к списку списков