将一些值连接到vararg参数数组

时间:2018-01-26 00:45:23

标签: generics compiler-errors kotlin variadic-functions

我一直试图在下面的函数中填补空白(val args = ...)。尝试了我能想到的一切,并找到了一个非常复杂的解决方案。我觉得有更好的方法,请建议更多的Kotlin-y方式。我错过了概念/操作员/乐趣/类型吗?

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")可以使用,如果没有打印,和/或代码重复是可以接受的。

3 个答案:

答案 0 :(得分:3)

啊哈!找到一个“更好”的解决方案,虽然它没有使用+

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

答案 1 :(得分:2)

这是一个泛型问题。 Kotlin中的数组是不变的,例如Java的情况就不是这样了。

文档说:

fun <T> asList(vararg ts: T)
     

&#34;在函数内部vararg - T类型的参数作为T的数组可见,即上例中的ts变量的类型为{{1} }}&#34;

Array<out T>只能作为Array<out T>的制作人,添加元素是不可能的。 T映射到的运算符仅在+上定义,即没有Array<T>修饰符。

您可以使方法接受out,而不使用任何投影,并允许数组也用作消费者。

答案 2 :(得分:0)

s1m0nw1澄清comment让我再次查看声明,我注意到该参数是public static int GetValueBeforeDot(string input){ return int.Parse(input.Substring(0, input.IndexOf('.')) .Where(char.IsDigit) .Aggregate(string.Empty, (e, a) => e + a)); }

<out T>

可能有用:

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

它强制自定义部件位于前面,这在我的情况下有效,但可能不是一般。