En este tutorial te mostraremos que son las propiedades delegadas en Kotlin, con el propósito de redireccionar la lógica de los accesores y mutadores de una propiedad hacia un objeto auxiliar.
Delegación De Propiedades
Al igual que viste en el tutorial sobre delegación de clases, las propiedades también pueden encomendar la lógica de sus getters y setters a una expresión personalizada.
Aplicar el patrón de delegación sobre propiedades es de utilidad cuando la asignación y/o lectura requieren una lógica que deseas evitar realizar una y otra vez.
Aunque puedes crear la delegación manualmente, recuerda que Kotlin te provee la palabra reservada by
para que el compilador genere todo el código repetitivo de la delegación. La sintaxis para ello es la siguiente:
// Sintaxis
val/var <nombrePropiedad>: <Tipo> by <expresion>
La expresión luego de by
será la que produzca el objeto delegado. El cuál atenderá la llamada de get()
y set()
con sus propios métodos equivalentes.
Propiedades De Solo Lectura Con Delegado
Cuando desees crear un delegado para una propiedad de solo lectura, es necesario declararle un método operador llamado getValue()
. Este será el que ejecutará la lógica del get()
de la propiedad.
El resultado de getValue()
debe ser del tipo o supertipo de la propiedad. Y los parámetros de su firma los configuras así:
thisRef
: Es la referencia al dueño de la referenciaproperty
: Es la referencia de la propiedad con tipoKProperty
Ejemplo: Crear una clase para líneas de factura con las propiedades de nombre de ítem, descripción, precio y cantidad comprada. Donde se debe delegar a la descripción la asignación de un String con el formato "Nombre de ítem. precio x cantidad = total"
.
import kotlin.reflect.KProperty
class InvoiceLine(val item: String, val price: Double, val quantity: Int) {
val description: String by Description()
}
fun main() {
val invoiceLine = InvoiceLine("Sandwich", 5.0, 1)
println(invoiceLine.description)
}
class Description {
operator fun getValue(thisRef: InvoiceLine, property: KProperty<*>): String {
val total = thisRef.price * thisRef.quantity
return buildString {
append(thisRef.item)
append("\n")
append("$${thisRef.price}")
append(" x ")
append("${thisRef.quantity}")
append(" = ")
append("$$total")
}
}
}
Salida:
Sandwich
$5.0 x 1 = $5.0
La delegación parte con la creación de la clase Description
y su método getValue()
. Este usa a thisReft
para acceder a la línea de la factura e invocar a las tres propiedades que serán usadas en la construcción del resultado final con la función buildString()
.
Luego consultamos a description
e imprimimos su resultado, delegando así su producción a Description
.
Propiedades Mutables Con Delegación
Similar a la delegación de propiedades de solo lectura, las propiedades mutables requieren la declaración del método setValue()
en su delegado para redirigir la lógica de set()
.
Este método recibe un tercer parámetro que representa el nuevo valor asignado a la propiedad.
Ejemplo: Crear una clase lectora de enteros desde el teclado. Realizar la conversión de la entrada del usuario a Int
a través de un delegado.
import kotlin.reflect.KProperty
class IntegerReader {
var input: String? by UserInput()
var number: Int = 0
}
class UserInput {
operator fun getValue(ir: IntegerReader, property: KProperty<*>): String = ir.number.toString()
operator fun setValue(ir: IntegerReader, property: KProperty<*>, value: String?) {
ir.number = value?.toIntOrNull() ?: 0
}
}
fun main() {
val reader = IntegerReader()
print("Digita número:")
reader.input = readLine()
println("Tu número es:${reader.number}")
}
Salida:
Digita número:125
Tu número es:125
En el código anterior creamos la clase IntegerReader()
con dos propiedades: number
para recibir el resultado de convertir a input
.
La clase UserInput()
representa al delgado de input
. En getValue()
obtenemos la conversión a String
de number
y en getValue()
tomamos el parámetro value
y lo convertimos a entero cada que sea modificado input
.
Únete Al Discord De Develou
Si tienes problemas con el código de este tutorial, preguntas, recomendaciones o solo deseas discutir sobre desarrollo Android conmigo y otros desarrolladores, únete a la comunidad de Discord de Develou y siéntete libre de participar como gustes. ¡Te espero!