将一些值连接到可变参数数组

Concatenate some value(s) to a vararg parameter array

我一直在尝试填补以下函数中的空白 (val args = ...)。尝试了我能想到的一切并找到了一个非常复杂的解决方案。我觉得有更好的方法,请提出更符合 Kotlin 风格的方法。我错过了 concept/operator/fun/type 吗?

class Result
interface Runner { fun execute(vararg tasks: String): Result }

fun Runner.debugExec(vararg tasks: String): Result {
// red: compile errors, mostly 
    //val args = tasks + "--debug" 
    //val args: Array<String> = tasks + "--debug"
    //val args: Array<out String> = tasks + "--debug"
    //val args = tasks + arrayOf("--debug")
    //val args = tasks + arrayOf<String>("--debug")
    //val args = tasks + listOf("--debug")
    //val args = tasks + (arrayOf("--debug") as Array<out String>)
    //val args = tasks + arrayOf<out String>("--debug") // Projections are not allowed here
    //val args = tasks.toList() + "--debug" // spread operator doesn't work
    //val args = tasks.plusElement("--debug") // cannot infer
    //val args = "--debug" + tasks // it's .toString() and spread operator doesn't work
// yellow: works, but warns
    //val args = (tasks as Array<String>) + "--debug" // unchecked cast
// green: but we must be able to do better, it's kotlin after all! 
    //val args = (tasks.toList() + "--debug").toTypedArray() // too many method calls
    println(args)
    return this.execute(*args)
}

我大多数时候遇到的编译错误是这样的:

None of the following functions can be called with the arguments supplied.
Array<T>.plus(T)
  where T cannot be inferred for
    operator fun <T> Array<T>.plus(element: T): Array<T> defined in kotlin.collections
Array<out String>.plus(Array<out String>)
  where T = CapturedTypeConstructor(out String) for
    operator fun <T> Array<T>.plus(elements: Array<out T>): Array<T> defined in kotlin.collections
Array<out String>.plus(Collection<String>)
  where T = CapturedTypeConstructor(out String) for
    operator fun <T> Array<T>.plus(elements: Collection<T>): Array<T> defined in kotlin.collections

注意:return this.execute(*tasks, "--debug")可以,如果没有打印,and/or代码重复是可以接受的。

这是泛型问题。 Kotlin 中的数组是不变的,Java 不是这种情况,例如

文档说:

fun <T> asList(vararg ts: T)

"Inside a function a vararg-parameter of type T is visible as an array of T, i.e. the ts variable in the example above has type Array<out T>."

一个Array<out T>只能作为T的生产者,不能添加个元素。 + 映射到的运算符仅在 Array<T> 上定义,即没有 out 修饰符。

您可以改为让方法接受 tasks: Array<String>,它不使用任何投影并允许数组也用作使用者。

啊哈!找到了一个 "better" 解决方案,尽管它没有使用 +:

val args = arrayOf(*tasks, "--debug")

s1m0nw1's clarifying 让我再次检查声明,我注意到参数是 <out T>:

public operator fun <T> Array<T>.plus(elements: Array<out T>): Array<T>

可能有用:

val args =  arrayOf("--debug") + tasks

它强制自定义部分在前面,这在我的情况下有效,但一般情况下可能无效。