kotlin: лямбда как реализация интерфейса - PullRequest
0 голосов
/ 16 мая 2019

JdbcTemplate существующей пружины имеет подпись:

public <T> List<T> query(String sql, RowMapper<T> rowMapper)

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

jdbcTemplate.query("select ...", { rs, _ -> 5 })

, но когда я объявляю ту же функцию в kotlin:

fun <T> query(sql: String, rowMapper: RowMapper<T>): List<T> = TODO()

и попробуйте вызвать его так же:

query("select ...", { rs, _ -> 5 })

я получаю ошибку компиляции

Ошибка вывода типа: забавный запрос (sql:String, rowMapper: RowMapper): список нельзя применять к (String, (???, ???) → Int)

мне нужно написать

query("select ...", RowMapper{ rs, _ -> 5 })

почему?есть ли способ просто предоставить лямбду?

1 Ответ

0 голосов
/ 16 мая 2019

Фон

В Java лямбда-выражение может быть передано в контексте, где ожидается функциональный интерфейс .Пример кода Java:

jdbcTemplate.query("select ...", (rs, _) -> 5);

В Kotlin не существует неявного преобразования из лямбда-выражений в интерфейсы.Вместо функциональных интерфейсов Kotlin предоставляет собственные типы функций с синтаксисом (Params) -> ReturnType.Для упрощения взаимодействия с Java, однако, существует преобразование лямбда-выражения Kotlin в Java функциональные интерфейсы путем добавления имени интерфейса:

query("select ...", RowMapper { rs, _ -> 5 })

Solution

Этоневозможно передать лямбду напрямую - однако вы можете написать функцию расширения, которая принимает тип функции и перенаправляет ее на query():

fun JdbcTemplate.query(sql: String, mapper: (A, B) -> Int) =
    query(sql, RowMapper { a, b -> mapper(a, b) })

. Затем она может быть вызвана втак, как вы хотите.Обратите внимание, что вам не нужны круглые скобки вокруг всех аргументов, поскольку специальный синтаксис Kotlin допускает конечные лямбда-выражения:

jdbc.query("select ...") { rs, _ -> 5 }

См. Также здесь ,где я объяснил это поведение подробно.

...