【问题标题】:Kotlin vararg array of array of anyKotlin vararg 任意数组的数组
【发布时间】:2019-04-26 15:56:06
【问题描述】:

我有一个接受形式可变参数的方法

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,我相信这是采用单个数组的 vararg。但是,我也不能传播。

【问题讨论】:

    标签: arrays generics kotlin variadic-functions


    【解决方案1】:

    我相信这与 T 被推断为对 arrayOf&lt;T&gt;(...) 的调用有关。

    我的理解是这样的:

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

    但是,在情况 1 中,arrayOf(1) 除了参数 1 之外没有其他类型信息,它是一个 Int,因此整个表达式被推断为具有类型 Array&lt;Int&gt;,这不是Array&lt;Any&gt; 的子类型(因为这里泛型类型参数的不变性)。不过,我不得不承认,错误消息并不是那么好。

    情况 2 也是如此,其中 aoa 的类型是 Array&lt;Array&lt;Int&gt;&gt; 而不是 Array&lt;Any&gt;。同样,错误消息不是很有帮助。

    情况 3 实际上与情况 1 相同,aoa 中的每个元素都应该是 Array&lt;Any&gt; 类型,但类型是 Array&lt;Int&gt;。如果ArrayT 中是协变的,它可能会起作用,这可能是“预期的Array&lt;out Any&gt;”的来源,但我真的不完全理解这里的错误消息。

    案例 4 与案例 0 类似,因为编译器有更多的本地类型信息(arrayOfArrays() 所期望的类型),因此它指导它在解释 @ 的声明时选择 T 的方式987654347@.

    【讨论】:

    • 感谢您抽出宝贵时间!这对我来说很有意义。在我的实际代码中,我只需要插入几个类型参数,所有错误都消失了。我还不明白为什么 vararg T 意味着 Array,但我希望最终会做到这一点;-)
    • @Matthias 我猜你已经看过了,但如果你想了解更多关于这些outin 关键字的信息,你可以read more about generics and variance in Kotlin here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 2012-01-19
    • 1970-01-01
    相关资源
    最近更新 更多