Kotlin vararg массив из любого массива - PullRequest
1 голос
/ 26 апреля 2019

У меня есть метод, принимающий vararg вида

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, принимающий один массив.Тем не менее, я не могу распространять это тоже.

1 Ответ

2 голосов
/ 26 апреля 2019

Я считаю, что это связано с тем, что T подразумевается в вызовах к arrayOf<T>(...).

Насколько я понимаю, это следующее:

В случае 0 ожидаемый * 1007 тип параметра равен 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, то, вероятно, отсюда и "ожидаемое Array<out Any>", но я действительно не совсем понимаю сообщение об ошибке здесь.

Случай 4 аналогичен случаю 0 в том смысле, что компилятор имеет больше информации о локальном типе (тип, ожидаемый arrayOfArrays()), и поэтому он определяет способ выбора T при интерпретации объявления toTypedArray().

...