Solución:
Actualmente en Kotlin stdlib no hay implementaciones de List<T>
(Map<K,V>
) ese no implementaría también MutableList<T>
(MutableMap<K,V>
). Sin embargo, debido a la función de delegación de Kotlin, las implementaciones se convierten en una sola línea:
class ImmutableList<T>(private val inner:List<T>) : List<T> by inner
class ImmutableMap<K, V>(private val inner: Map<K, V>) : Map<K, V> by inner
También puede mejorar la creación de contrapartes inmutables con métodos de extensión:
fun <K, V> Map<K, V>.toImmutableMap(): Map<K, V> {
if (this is ImmutableMap<K, V>) {
return this
} else {
return ImmutableMap(this)
}
}
fun <T> List<T>.toImmutableList(): List<T> {
if (this is ImmutableList<T>) {
return this
} else {
return ImmutableList(this)
}
}
Lo anterior evita que una persona que llama modifique el List
(Map
) enviando a una clase diferente. Sin embargo, todavía hay razones para crear una copia del contenedor original para evitar problemas sutiles como ConcurrentModificationException:
class ImmutableList<T> private constructor(private val inner: List<T>) : List<T> by inner {
companion object {
fun <T> create(inner: List<T>) = if (inner is ImmutableList<T>) {
inner
} else {
ImmutableList(inner.toList())
}
}
}
class ImmutableMap<K, V> private constructor(private val inner: Map<K, V>) : Map<K, V> by inner {
companion object {
fun <K, V> create(inner: Map<K, V>) = if (inner is ImmutableMap<K, V>) {
inner
} else {
ImmutableMap(hashMapOf(*inner.toList().toTypedArray()))
}
}
}
fun <K, V> Map<K, V>.toImmutableMap(): Map<K, V> = ImmutableMap.create(this)
fun <T> List<T>.toImmutableList(): List<T> = ImmutableList.create(this)
Si bien lo anterior no es difícil de implementar, ya existen implementaciones de listas y mapas inmutables en las colecciones de Guava y Eclipse.
Usar Colecciones convertir un Mudable lista para Inmutable lista, Ejemplo:
Lista mutable:
val mutableList = mutableListOf<String>()
Convierte a lista inmutable:
val immutableList = Collections.unmodifiableList(mutableList)
Como se mencionó aquí y aquí, necesitaría escribir su propio List
implementación para eso, o use una existente (ImmutableList de Guava me viene a la mente, o Eclipse Collections como sugirió Andrew).
Kotlin aplica la (im) mutabilidad de la lista solo por interfaz. No existen List
implementaciones que tampoco implementan MutableList
.
Incluso el idiomático listOf(1,2,3)
termina llamando a Kotlin’s ArraysUtilJVM.asList()
que llama a Java Arrays.asList()
que devuelve un Java antiguo simple ArrayList
.
Si le importa más proteger su propia lista interna que la inmutabilidad en sí, puede, por supuesto, copiar la colección completa y devolverla como un List
, al igual que hace Kotlin:
return ArrayList(original)