Kotlin: ¿"eso" asignable?

Estoy tratando de simplificar el código Parcelable en Kotlin:

public class C() : Parcelable { var b1: Boolean = false var b2: Boolean = false var b3: Boolean = false var i1: Int = 0 var i2: Int = 0 val parcelBooleans = listOf(b1, b2, b3) val parcelInts = listOf(i1, i2) override fun writeToParcel(p: Parcel, flags: Int) { parcelBooleans.forEach { p.writeBoolean(it) } parcelInts.forEach { p.writeInt(it) } } private fun readFromParcel(p: Parcel) { parcelBooleans.forEach{ it = p.readBoolean() } // does not compile as "it" is a "val" } // ... parcel creator bla bla } 

writeBoolean () y readBoolean () son funciones de extensión.

¿Hay alguna forma de tener un para cada list con un "it" asignable?

Actualización: en un comentario a una de las respuestas, el autor aclara esta pregunta como:

Mi punto es que mi list no es mutable, los elementos adentro son. Los elementos son mis properties Pero me estoy dando count de que tal vez, listOf está haciendo una copy de valor de mis properties … así que o bien debo confiar en la reflexión, o envolver el tipo básico en una class para permitir el cambio en su valor.

La intención es a través de la list de parcelBooleans lectura parcelBooleans que contiene references a b1 , b2 y b3 modificar los valores de b1 , b2 y b3 ; pero no muta la list en sí misma.

Actualización: KT-7033 ha sido reparado, esta respuesta ahora funciona sin requerir el kotlin-reflect.jar

Creo que una forma simple de lograr tus deseos es usar references de properties , pero ten en count que debes proporcionar kotlin-reflect.jar en classpath (hasta que no se haya reparado el KT-7033 ). Además, se puede simplificar después de que se arregle KT-6947 .

 public class C_by_Reflection() : Parcelable { var b1: Boolean = false var b2: Boolean = false var b3: Boolean = false var i1: Int = 0 var i2: Int = 0 val parcelBooleans = listOf(::b1, ::b2, ::b3) val parcelInts = listOf(::i1, ::i2) override fun writeToParcel(p: Parcel, flags: Int) { parcelBooleans.forEach { p.writeBoolean(it.get(this)) } parcelInts.forEach { p.writeInt(it.get(this)) } } private fun readFromParcel(p: Parcel) { parcelBooleans.forEach{ it.set(this, p.readBoolean()) } } // ... parcel creator bla bla } 

Otra solución simple es usar properties delegadas :

 public class C_by_Delgates() : Parcelable { val mapBooleans = hashMapOf<String, Any?>() var b1: Boolean by mapBooleans var b2: Boolean by mapBooleans var b3: Boolean by mapBooleans val mapInts = hashMapOf<String, Boolean>() var i1: Int by mapInts var i2: Int by mapInts override fun writeToParcel(p: Parcel, flags: Int) { mapBooleans.forEach { p.writeBoolean(it.value as Boolean) } mapInts.forEach { p.writeInt(it.value as Int) } } private fun readFromParcel(p: Parcel) { mapBooleans.forEach { mapBooleans[it.key] = p.readBoolean() } } // ... parcel creator bla bla } 

NOTA: La pregunta no está clara si el autor intenta mutar las properties b1 , b2 , b3 través de una reference dentro de la list. O si está tratando de modificar el contenido de la list parcelBooleans que es una copy de los valores de las properties. Si es el primero, vea la respuesta de @Bashor (o simplemente haga que los valores de la list sean algo que contenga subelementos), si es el segundo, esta respuesta es correcta.

Dadas las funciones de extensión definidas en esta otra pregunta sobre el desbordamiento de stack "cómo se modifican los contenidos de una list al iterar" , puede cambiar el código simplemente:

 public class C() : Parcelable { var b1: Boolean = false var b2: Boolean = false var b3: Boolean = false var i1: Int = 0 var i2: Int = 0 // CHANGED: use mutable list, array, or primitive array val parcelBooleans = arrayListOf(b1, b2, b3) val parcelInts = listOf(i1, i2) override fun writeToParcel(p: Parcel, flags: Int) { parcelBooleans.forEach { p.writeBoolean(it) } parcelInts.forEach { p.writeInt(it) } } private fun readFromParcel(p: Parcel) { // CHANGED: using the extension function parcelBooleans.mapInPlace { p.readBoolean() } } // ... parcel creator bla bla } 

Crear su propio iterador sería la forma de OOP para hacerlo.

Si quieres ir de la manera más funcional, puedes usar map (), por ej.

 private fun readFromParcel(p: Parcel) { val mappedBooleans = parcelBooleans.map{ p.readBoolean() } } 

map () es similar a paraEach, usa el valor de retorno de cada ejecución lambda para crear una nueva list <>

Una forma de hacerlo es mapear cada valor:

 parcelBooleans = parcelBooleans.map{ p.readBoolean() } 

parcelBooleans embargo, parcelBooleans hacer de parcelBooleans una variable mutable.

Descubrí que mi código al principio no puede funcionar ya que la list de hace una copy del valor de las properties.

Así que envuelvo los types básicos en una class simple con el método get / set:

 public class MBoolean() { var internal: Boolean = false constructor(b: Boolean) : this() { internal = b } fun set(b: Boolean) { internal = b } fun get(): Boolean { return internal } } public class MInt() { private var internal: Int = 0 constructor(i: Int) : this() { set(i) } public fun set(i: Int) { internal = i } public fun get(): Int { return internal } } override fun writeToParcel(p: Parcel, flags: Int) { parcelBooleans.forEach { p.writeBoolean(it.get()) } parcelInts.forEach { p.writeInt(it.get()) } } private fun readFromParcel(p: Parcel) { parcelBooleans.forEach { it.set(p.readBoolean()) } parcelInts.forEach { it.set(p.readInt()) } }