Я сталкиваюсь с ошибкой компиляции при попытке использовать ссылки 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 Что касается второго вопроса – эта функция еще не поддерживается.