我有一个接受形式为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。但是,我也无法传播它。
答案 0 :(得分:2)
我相信这与对T
的调用中推断出的arrayOf<T>(...)
有关。
我的理解方式如下:
在情况0中,arrayOfArrays()
期望的参数类型为Array<Any>
,因此使编译器将Array<Any>
推断为表达式arrayOf(1)
的类型。然后,编译器检查1是Any
的实例,这是正确的(因为Int
是Any
的子类型),因此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
的声明。