есть ли способ отправить обнуляемую функцию как параметр в Kotlin? - PullRequest
1 голос
/ 13 января 2020

Я пытаюсь использовать интерфейсную функцию publi c (как я узнал об этом в Java) в Kotlin.

Для этого я создал свой метод

fun foo(input: List<String>, modifier1: Function<List<String>>? = null){

}

насколько я помню здесь, я должен быть в состоянии сделать modifier1.apply(input)

, но кажется, что это невозможно (хотя можно сделать modifier1.apply {input})

Читать дальше об этом я нашел это:

Kotlin: как передать функцию в качестве параметра другому?

Итак, я изменил свою сигнатуру метода следующим образом:

fun foo(input:String,  modifier2: (List<String>) -> (List<String>){
}

Здесь я могу сделать modifier2(input)

, и я могу назвать foo таким образом

service.foo(input, ::myModifierFunction)

где

fun myModifierFunction(input:List<String>):List<String>{
   //do something
   return input
}

Пока это кажется возможным, но недопустимо иметь ссылку на функцию как обнуляемую, есть ли способ сделать это? или использовать функцию?

Ответы [ 3 ]

2 голосов
/ 13 января 2020

Вы использовали kotlin.Function вместо java.util.function.Function в первом примере. Обратите внимание, что последний принимает 2 универсальных c типа: 1 для входящего параметра и 1 для результирующего.

Метод apply, который вы видели, по умолчанию Kotlin one: apply, а не интерфейс Java Function.

Если вы действительно хотите иметь функцию Java в качестве обнуляемого типа, должно работать следующее:

fun foo(input: List<String>, modifier1: java.util.function.Function<List<String>, List<String>>? = null) {
    modifier1?.apply(input) ?: TODO("what should be done if there wasn't passed any function?")
}

Kotlin вариант для того же:

fun foo(input: List<String>, modifier1: ((List<String>) -> List<String>)? = null) {
     modifier1?.invoke(input) ?: TODO("what should be done if there wasn't passed any function?")
}

Может быть, также функция по умолчанию, такая как { it } вместо null, может лучше удовлетворить ваши потребности? (Java вариант будет Function.identity()):

// java   modifier1 : Function<List<String>, List<String>> = Function.identity()
// kotlin modifier1 : (List<String>) -> List<String> = { it }
1 голос
/ 13 января 2020

Вы можете сделать ссылку обнуляемой просто с помощью ? - единственный недостаток в том, что весь тип функции должен быть вначале в скобках:

fun foo(input: String,  modifier2: ((List<String>) -> List<String>)? = null) {
}

При необходимости, modifier2 необязательно; если указан, он может содержать ноль или функцию, принимающую и возвращающую список строк.

Как уже упоминалось в другом ответе, kotlin.Function - это не то же самое, что java.util.function.Function - хотя на практике вы не нужно ссылаться на них напрямую, так как запись -> проще.

0 голосов
/ 13 января 2020

Если вы хотите передать функцию, которая принимает List<String> в качестве своего параметра и не возвращает ничего значащего, тип для вас - Function1<List<String>, Unit>. Имя метода для вызова функции - invoke(), что вы также можете сделать с помощью обычных круглых скобок, если оно не имеет значения NULL. В целом, ваш код может выглядеть примерно так:

fun foo(input: List<String>, modifier1: Function1<List<String>, Unit>? = null) {
    modifier1?.invoke(input)
}

1 в названии типа Function1 означает, что это функция с одним параметром, есть также Function0, Function2, et c.

Сам по себе тип Function нельзя использовать для вызова этой функции, поскольку это пустой интерфейс маркера. Все функции реализуют это независимо от того, сколько у них параметров.

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