Kotlin: Можете ли вы использовать именованные аргументы для varargs?
Например, у вас может быть функция со сложной сигнатурой и varargs:
fun complicated(easy: Boolean = false, hard: Boolean = true, vararg numbers: Int)
Было бы разумно, что вы должны иметь возможность вызвать эту функцию следующим образом:
complicated(numbers = 1, 2, 3, 4, 5)
К сожалению, компилятор этого не допускает.
Можно ли использовать именованные аргументы для varargs? Есть ли какие-нибудь умные способы обхода?
Ответы
Ответ 1
Его можно обойти, переместив необязательные аргументы после vararg
:
fun complicated(vararg numbers: Int, easy: Boolean = false, hard: Boolean = true) = {}
Тогда его можно назвать следующим:
complicated(1, 2, 3, 4, 5)
complicated(1, 2, 3, hard = true)
complicated(1, easy = true)
Обратите внимание, что завершающие необязательные параметры должны всегда передаваться с именем. Это не скомпилируется:
complicated(1, 2, 3, 4, true, true) // compile error
Другим вариантом является vararg
сахара vararg
для явного массива param:
fun complicated(easy: Boolean = false, hard: Boolean = true, numbers: IntArray) = {}
complicated(numbers = intArrayOf(1, 2, 3, 4, 5))
Ответ 2
Чтобы передать именованный аргумент параметру vararg, используйте оператор spread:
complicated(numbers = *intArrayOf(1, 2, 3, 4, 5))
Ответ 3
Kotlin Docs четко говорит, что:
Переменная количество аргументов (Varargs)
Параметр функции (обычно последний) может быть отмечен модификатором vararg
:
fun <T> asList(vararg ts: T): List<T> {
val result = ArrayList<T>()
for (t in ts) // ts is an Array
result.add(t)
return result
}
позволяя передать переменное количество аргументов функции:
val list = asList(1, 2, 3)
Внутри функции vararg
-parameter типа T
видна как массив из T
, т. ts
Переменная ts
в приведенном выше примере имеет тип Array<out T>
.
Только один параметр может быть отмечен как vararg
. Если параметр vararg
не является последним в списке, значения для следующих параметров могут быть переданы с использованием синтаксиса с именованным аргументом или, если параметр имеет тип функции, передавая лямбду вне круглых скобок.
Когда мы вызываем vararg
-function, мы можем передавать аргументы один за другим, например asList(1, 2, 3)
, или, если мы уже имеем массив и хотим передать его содержимое функции, мы используем распространение оператора (префикс массив с *
):
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
От: https://kotlinlang.org/docs/reference/functions.html#variable-number-of-arguments-varargs
Чтобы возобновить работу, вы можете сделать это с помощью оператора спредов, чтобы он выглядел так:
complicated(numbers = *intArrayOf(1, 2, 3, 4, 5))
Надеюсь, это поможет
Ответ 4
Параметр vararg может быть в любом месте в списке параметров. См. Пример ниже о том, как его можно вызывать с помощью различного набора параметров. BTW любой вызов также может обеспечить лямбда после закрытых круглых скобок.
fun varargs(
first: Double = 0.0,
second: String = "2nd",
vararg varargs: Int,
third: String = "3rd",
lambda: ()->Unit = {}
) {
...
}
fun main(args: Array<String>) {
val list = intArrayOf(1, 2, 3)
varargs(1.0, "...", *list, third="third")
varargs(1.0, "...", *list)
varargs(1.0, varargs= *list, third="third")
varargs(varargs= *list, third="third")
varargs(varargs= *list, third="third", second="...")
varargs(varargs= *list, second="...")
varargs(1.0, "...", 1, 2, 3, third="third")
varargs(1.0, "...", 1, 2, 3)
varargs(1.0)
varargs(1.0, "...", third="third")
varargs(1.0, third="third")
varargs(third="third")
}