Kotlin:你可以为可变参数使用命名参数吗?

Posted

技术标签:

【中文标题】Kotlin:你可以为可变参数使用命名参数吗?【英文标题】:Kotlin: Can you use named arguments for varargs? 【发布时间】:2016-12-20 19:57:50 【问题描述】:

例如,您的函数可能具有复杂的签名和可变参数:

fun complicated(easy: Boolean = false, hard: Boolean = true, vararg numbers: Int)

你应该能够像这样调用这个函数是有道理的:

complicated(numbers = 1, 2, 3, 4, 5)

不幸的是编译器不允许这样做。

是否可以对可变参数使用命名参数?有什么巧妙的变通办法吗?

【问题讨论】:

【参考方案1】:

要将命名参数传递给可变参数,请使用spread operator:

complicated(numbers = *intArrayOf(1, 2, 3, 4, 5))

【讨论】:

【参考方案2】:

可以通过在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 糖用于显式数组参数:

fun complicated(easy: Boolean = false, hard: Boolean = true, numbers: IntArray) = 

complicated(numbers = intArrayOf(1, 2, 3, 4, 5))

【讨论】:

更改签名对函数的用户不好。按照传统, vararg 是最后一个,当你想像你指出的那样正常调用它时,它可能会导致问题; numbers = *intArrayOf(...) 是这里的路。【参考方案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 类型的参数 T 可以作为 T 的数组,即上例中的 ts 变量具有类型 Array&lt;out T&gt;.

只有一个参数可以标记为vararg。如果有vararg 参数 不是列表中的最后一个,以下参数的值 可以使用命名参数语法传递,或者,如果参数 有一个函数类型,通过在括号外传递一个 lambda。

当我们调用vararg-函数时,我们可以一个接一个地传递参数, 例如asList(1, 2, 3),或者,如果我们已经有一个数组并且想要 将其内容传递给函数,我们使用 spread 运算符 (在数组前面加上*):

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】:

可变参数可以是参数列表中的任何位置。请参阅下面的示例,了解如何使用不同的参数集调用它。顺便说一句,任何调用也可以在右括号后提供 lambda。

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")

【讨论】:

以上是关于Kotlin:你可以为可变参数使用命名参数吗?的主要内容,如果未能解决你的问题,请参考以下文章

参数调用

将 Kotlin 数组转换为 Java 可变参数

Scala可变参数列表,命名参数和参数缺省

Kotlin 使用vararg可变参数

可变参数,你还为方法的参数而烦恼吗?可变参数,让你的头发从此“茂密”!

参数定义的顺序必须是:必选参数默认参数可变参数命名关键字参数和关键字参数。