Estoy aprendiendo conceptos de kotlin y tuve la siguiente pregunta cuando estaba revisando el tema Matrices.
Creé un vacío
val empty = arrayOf<Int>() empty[0] = 2
Entonces, el código anterior fallará y causará ArrayIndexOutOfBoundsException, lo cual tiene sentido porque el tamaño de una matriz no se puede cambiar y dado que la matriz se inicializó sin tamaño, se trata como una matriz vacía.
Aquí es donde pensé que esto se pone interesante
var emptyArray = arrayOf<Int>() emptyArray += 1 emptyArray += 2
El código anterior no falla y cuando imprimo los elementos obtengo los resultados. Supongo que sucede algo cuando intento agregar un elemento a un índice en lugar de agregarlo directamente, pero no pude encontrar ninguna documentación que explique lo que sucede debajo del capó. ¿Puede alguien por favor explicar
Esto se debe a la sobrecarga de los operadores de asignación aumentada de Kotlin.
Para las operaciones de asignación, por ejemplo a += b, el compilador realiza los siguientes pasos:
- Si la función de la columna de la derecha está disponible:
- [...]
- De lo contrario, intente generar código para
a = a + b
(esto incluye una verificación de tipo: el tipo dea + b
debe ser un subtipo dea
).
"la función de la columna de la derecha" se refiere a la columna de la derecha de la tabla que no incluí en la cita, que son básicamente las funciones de operador plusAssign
, minusAssign
, timesAssign
, etc. Por supuesto, estas funciones no existen para las matrices, por lo que el segundo punto se aplica aquí.
Para generar código para a = a + b
, debe haber una función de operador plus
para matrices, tomando un elemento de esa matriz y devolviendo una matriz, de modo que se traduzca a a = a.plus(b)
. De hecho, existe una función de operador de este tipo para Array<T>
.
operator fun <T> Array<T>.plus(element: T): Array<T>
Así que para resumir:
emptyArray += 1
se traduce en
emptyArray = emptyArray + 1
que se traduce en:
emptyArray = emptyArray.plus(1)
En el segundo ejemplo, el operador + llama a una función llamada plus
y luego asigna el resultado a la variable.
Una mirada a la definición da la siguiente función:
/** * Returns an array containing all elements of the original array and then the given [element]. */ public actual operator fun <T> Array<T>.plus(element: T): Array<T> { val index = size val result = java.util.Arrays.copyOf(this, index + 1) result[index] = element return result }
Como veis, se hace una copia del original pero una más grande. A continuación, el nuevo elemento se asigna al nuevo espacio vacío.
En el ejemplo, se asignan un total de tres matrices. Primero una matriz vacía, luego de 1 tamaño y finalmente de 2 tamaños, que es el resultado final. Cada matriz aún no puede cambiar su tamaño.
Tenga en cuenta que debe usar var
y val
generará un error de "no se puede reasignar val".