Разница в том, что в Java массивы ковариантны, то есть допустимо следующее:
public static void main(String[] args) {
Number[] numbers = new Number[0];
Integer[] ints = new Integer[0];
numbers = ints;
}
Однако массивы не являются ковариантными в Kotlin, то есть следующее выдает ошибку компиляции:
var numbers: Array<Number> = arrayOf()
val ints: Array<Int> = arrayOf()
numbers = ints // error: required Array<Number>, found Array<Int>
Однако вы можете объявить, что массив является производителем (то есть вы обещаете, что никогда ничего не вставите в него; компилятор позаботится об этом) с ключевым словом out
.Это делает массив ковариантным, то есть справедливо следующее:
var numbers: Array<out Number> = arrayOf() // we will only extract Numbers out of this array
val ints: Array<Int> = arrayOf()
numbers = ints // this is ok
Учитывая, что, если vararg va: Number
не обрабатывался как Array<out Number>
, то вы могли бы вызывать свой метод только с Number
объектамиа не со своими подклассами.То есть следующее не получится:
fun main() {
varargFun(arrayOf<Int>(1, 2))
}
fun varargFun(va: Array<Number>) {
arrayFun(va)
}
Но опять же, с out
(что и делает vararg
), оно волшебным образом работает:
fun main() {
varargFun(arrayOf<Int>(1, 2)) // error: required Array<Number>, found Array<Int>
}
fun varargFun(va: Array<out Number>) {
arrayFun(va)
}