任意数组的 Kotlin 可变参数数组
Kotlin vararg array of array of any
我有一个方法接受形式的可变参数
fun arrayOfArrays(vararg aoa: Array<Any>) {
}
现在,我很难理解如何调用这个方法,例如
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
}
更新:
在得到同事的提醒后,我们认为向 arrayOf() 添加类型可以解决我的一些问题,即以下内容现在可以正常工作:
fun callArrayOfArrays() {
arrayOfArrays(arrayOf(1), arrayOf(1))
val a = arrayOf<Any>(1)
arrayOfArrays(a, a)
val aoa = arrayOf<Array<Any>>(a)
arrayOfArrays(*aoa)
arrayOfArrays(aoa.toList().toTypedArray())
arrayOfArrays(*(aoa.toList().toTypedArray()))
}
我仍然认为前者也应该没问题。我确实渴望对这种行为有一个可以理解的解释。
我很欣赏案例 0 的工作原理,但我无法理解所有其他案例。
对于情况 1,我希望将 arrayOf(1) 分配给变量不会改变语义,但我们就是这样。
对于案例 2,我希望它像我期望的第一个案例一样工作,只是 "Any" 在这里是一个数组。
对于案例 3,我可以看出区别,但我不明白,当然也不知道如何使它起作用。
对于案例 4,我相信这是采用单个数组的可变参数。不过我也传不出去
我认为这与 T
在对 arrayOf<T>(...)
.
的调用中的推断有关
我的理解是这样的:
在情况 0 中,arrayOfArrays()
期望的参数类型是 Array<Any>
,因此它使编译器将 Array<Any>
推断为表达式 arrayOf(1)
的类型。然后编译器检查 1 是 Any
的实例,这是真的(因为 Int
是 Any
的子类型),因此 1 是 arrayOf<Any>()
的有效参数.
但是,在情况 1 中,arrayOf(1)
除了参数 1 之外没有其他类型信息,它是一个 Int
,因此表达式作为一个整体被推断为具有类型 Array<Int>
,它不是 Array<Any>
的子类型(因为这里泛型类型参数的不变性)。不过,我不得不承认,错误信息不是那么好。
情况 2 也是如此,其中 aoa
的类型是 Array<Array<Int>>
而不是 Array<Any>
。同样,错误消息不是很有帮助。
情况 3 实际上与情况 1 相同,其中 aoa
中的每个元素都应为 Array<Any>
类型,但实际为 Array<Int>
类型。如果 Array
在 T
中是协变的,它可能会工作,这可能是 "expected Array<out Any>
" 的来源,但我真的不完全理解这里的错误消息。
案例 4 与案例 0 相似,因为编译器具有更多本地类型信息(arrayOfArrays()
期望的类型),因此它指导选择 T
的方式在解释 toTypedArray()
.
的声明时
我有一个方法接受形式的可变参数
fun arrayOfArrays(vararg aoa: Array<Any>) {
}
现在,我很难理解如何调用这个方法,例如
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
}
更新: 在得到同事的提醒后,我们认为向 arrayOf() 添加类型可以解决我的一些问题,即以下内容现在可以正常工作:
fun callArrayOfArrays() {
arrayOfArrays(arrayOf(1), arrayOf(1))
val a = arrayOf<Any>(1)
arrayOfArrays(a, a)
val aoa = arrayOf<Array<Any>>(a)
arrayOfArrays(*aoa)
arrayOfArrays(aoa.toList().toTypedArray())
arrayOfArrays(*(aoa.toList().toTypedArray()))
}
我仍然认为前者也应该没问题。我确实渴望对这种行为有一个可以理解的解释。
我很欣赏案例 0 的工作原理,但我无法理解所有其他案例。
对于情况 1,我希望将 arrayOf(1) 分配给变量不会改变语义,但我们就是这样。
对于案例 2,我希望它像我期望的第一个案例一样工作,只是 "Any" 在这里是一个数组。
对于案例 3,我可以看出区别,但我不明白,当然也不知道如何使它起作用。
对于案例 4,我相信这是采用单个数组的可变参数。不过我也传不出去
我认为这与 T
在对 arrayOf<T>(...)
.
我的理解是这样的:
在情况 0 中,arrayOfArrays()
期望的参数类型是 Array<Any>
,因此它使编译器将 Array<Any>
推断为表达式 arrayOf(1)
的类型。然后编译器检查 1 是 Any
的实例,这是真的(因为 Int
是 Any
的子类型),因此 1 是 arrayOf<Any>()
的有效参数.
但是,在情况 1 中,arrayOf(1)
除了参数 1 之外没有其他类型信息,它是一个 Int
,因此表达式作为一个整体被推断为具有类型 Array<Int>
,它不是 Array<Any>
的子类型(因为这里泛型类型参数的不变性)。不过,我不得不承认,错误信息不是那么好。
情况 2 也是如此,其中 aoa
的类型是 Array<Array<Int>>
而不是 Array<Any>
。同样,错误消息不是很有帮助。
情况 3 实际上与情况 1 相同,其中 aoa
中的每个元素都应为 Array<Any>
类型,但实际为 Array<Int>
类型。如果 Array
在 T
中是协变的,它可能会工作,这可能是 "expected Array<out Any>
" 的来源,但我真的不完全理解这里的错误消息。
案例 4 与案例 0 相似,因为编译器具有更多本地类型信息(arrayOfArrays()
期望的类型),因此它指导选择 T
的方式在解释 toTypedArray()
.