Kotlin vararg任意数组的数组

时间:2019-04-26 15:56:07

标签: arrays generics kotlin variadic-functions

我有一个接受形式为vararg的方法

['h', 't', 'h', 'd', 'y', 'd']

现在,我很难理解如何调用此方法,例如

fun arrayOfArrays(vararg aoa: Array<Any>) {
}

更新: 在得到同事的提示后,我们发现向arrayOf()添加类型可以解决我的一些问题,即以下操作现已生效:

fun callArrayOfArrays() {
    arrayOfArrays(arrayOf(1), arrayOf(1))      // 0) works
    val a = arrayOf(1)
    arrayOfArrays(a, a)                        // 1) type mismatch: inferred type Array, but Array was expected
    val aoa = arrayOf(a)
    arrayOfArrays(aoa)                         // 2) type mismatch: inferred type Array<array>, but Array was expected
    arrayOfArrays(*aoa)                        // 3) type mismatch: inferred type Array<array>, but Array<out array> was expected
    arrayOfArrays(aoa.toList().toTypedArray()) // 4) works
}

我仍然相信前者也可以。我很想对此行为做一个可以理解的解释。

我对案例0有用,但我无法理解所有其他案例。

对于情况1,我希望将arrayOf(1)分配给变量不会改变语义,但是我们就在这里。

对于第2种情况,我希望它的工作原理与第一种情况一样,只是这里的“ Any”是一个数组。

对于情况3,我可以看到其中的区别,但我不了解它,当然也不知道如何进行这项工作。

对于情况4,我相信这是采用单个数组的vararg。但是,我也无法传播它。

1 个答案:

答案 0 :(得分:2)

我相信这与对T的调用中推断出的arrayOf<T>(...)有关。

我的理解方式如下:

在情况0中,arrayOfArrays()期望的参数类型为Array<Any>,因此使编译器将Array<Any>推断为表达式arrayOf(1)的类型。然后,编译器检查1是Any的实例,这是正确的(因为IntAny的子类型),因此1是arrayOf<Any>()的有效参数。

但是,在情况1中,arrayOf(1)除了参数1(Int)外没有其他类型信息,因此可以推断整个表达式的类型为{{1} },它不是Array<Int>的子类型(由于此处泛型类型参数的不变性)。但是,我必须承认错误消息不是很好。

情况2同样,其中Array<Any>的类型为aoa而不是Array<Array<Int>>。同样,错误消息不是很有帮助。

第3种情况与第1种情况完全相同,其中Array<Any>中的每个元素应为aoa类型,但为Array<Any>类型。如果Array<Int>Array是协变的,这可能会起作用,这可能就是“预期的T”的来源,但是我真的不完全理解这里的错误消息。

在编译器具有更多本地类型信息(Array<out Any>所期望的类型)的意义上,情况4与情况0类似,因此,情况4指导了解释时选择arrayOfArrays()的方式。 T的声明。