преобразование Java-метода в kotln. Вернуть лямбда-выражение - PullRequest
2 голосов
/ 22 июня 2019
kotlin 1.3.31

У меня есть следующий фрагмент кода в Java, который я пытаюсь преобразовать в Kotlin

private ArgumentMatcher<List<Person> customArgumentMatcher(final int size) {
    return argument -> argument.size() == size;
}

Мое понимание вышеизложенного - это объявление метода, в котором ArgumentMatcher имеет тип возвращаемого значения иМетод интерфейса выполняется в лямбда-выражении и возвращается логическое значение.Поправьте меня, если я ошибаюсь в своем объяснении.

Однако, когда я пытаюсь преобразовать это в Kotlin

 private fun customArgumentMatcher(size: Int): ArgumentMatcher<List<Person>> {
    return { argument -> argument.size == size }
 }

, я получаю следующую ошибку:

Required ArgumentMatcher<List<Person>>
found: (???) -> Boolean

Большое спасибо за любые предложения,

Ответы [ 2 ]

4 голосов
/ 22 июня 2019

Чтобы добавить фон к другому ответу:

Это одна из немного неловких областей в Kotlin, с точки зрения взаимодействия с Java. Но это печальное последствие того, что Kotlin стал лучшим языком сам по себе! Позвольте мне попытаться объяснить ...

Когда Java добавил лямбды, они сделали это таким образом (как и в случае с дженериками до этого), чтобы внести минимум изменений в работу языка. Поэтому они не делали функции первоклассными типами. Вместо этого они закрепили существующую практику использования интерфейсов. Например, если вы хотите, чтобы о чем-то сообщали ActionEvent s, вы бы реализовали интерфейс ActionListener. Это единственный метод с именем actionPerformed(), принимающий параметр ActionEvent.

Они не хотели менять то, как все это работало, поэтому в Java 8+ лямбда - это просто более лаконичный способ реализации некоторого интерфейса. Контекст (то есть метод, который вы вызываете, или тип переменной, которой вы его назначаете) сообщает компилятору, какой тип интерфейса вы хотите - это должен быть «функциональный интерфейс» с Single Abstract Method (SAM) - и затем компилятор генерирует реализацию. Есть несколько оптимизаций, но это в основном то, что вы делали в Java 7-. Это не так уж плохо работает, но есть много неудобных угловых случаев, потому что функции не являются полными первоклассными объектами.

Котлин, с другой стороны, имеет правильные типы функций. Это гораздо более мощный и гибкий инструмент, но он не соответствует способу работы Java.

Компилятор Kotlin имеет несколько особых случаев, позволяющих автоматически преобразовывать лямбду в реализацию Java SAM-интерфейса. (Однако это не относится к реализации интерфейсов Kotlin, что вызывает некоторую путаницу.)

В тех случаях, когда вы передаете лямбду, реализующую SAM, непосредственно методу, компилятор может определить его тип. (Как во втором примере @ Slaw.)

Но в других случаях вам нужно указать имя интерфейса перед открывающей фигурной скобкой. (Как в первом примере @ Slaw.)

3 голосов
/ 22 июня 2019

Поскольку ArgumentMatcher является функциональным интерфейсом Java, вам необходимо использовать:

fun customArgumentMatcher(size: Int): ArgumentMatcher<List<Person>> {
    return ArgumentMatcher { argument -> argument.size == size }
}

См. Раздел SAM Conversions в справочнике Kotlin.


Вы также можете использовать:

fun customArgumentMatcher(size: Int) = ArgumentMatcher<List<Person>> { it.size == size }

См. ответ Гиддса , чтобы узнать, почему необходим вышеуказанный синтаксис.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...