En este tutorial verás el uso de propiedades respaldadas por mapas. Esta es otra utilidad de las propiedades delegadas, donde usarás mapas como delegados para la lectura y escritura de los valores de tus propiedades.
Delegar A Mapa Inmutable
Para tomar el valor de las propiedades delegadas desde en un mapa, usa la cláusula by
en la declaración de la misma, seguido del mapa que actuará como delegado.
val propiedad: Tipo by mapa
La propiedad tomará el valor del par al que corresponde su nombre como clave. Esta lógica se ejecuta dentro de la funciones de extensión Map<K, V>.getValue()
.
Ejemplo:
Crear el modelo de un jugador de NBA a partir de un mapa con sus datos básicos: primer nombre, apellido, ID de jugador e ID de equipo.
class NbaPlayer(nbaInfo: Map<String, Any?>) {
val firstName: String by nbaInfo
val lastName: String by nbaInfo
val playerId: Int by nbaInfo
val teamId: Int by nbaInfo
override fun toString(): String {
var toPrint = "Nombre: $firstName\n"
toPrint += "Apellido: $lastName\n"
toPrint += "Id jugador: $playerId\n"
toPrint += "Id equipo: $teamId\n"
return toPrint
}
}
La solución anterior declara la clase NbaPlayer
con el mapa nbaInfo
como parámetro de entrada. Luego definimos 4 propiedades de solo lectura para los datos y se las delegamos al mapa.
Ahora creemos una instancia de NbaPlayer
y deleguemos su inicialización a un mapa cuyas claves correspondan a las propiedades:
fun main() {
val playerMap = mapOf(
"firstName" to "Jaylen",
"lastName" to "Adams",
"playerId" to 1629121,
"teamId" to 1610612749
)
val player1 = NbaPlayer(playerMap)
println(player1)
}
Salida:
Nombre: Jaylen
Apellido: Adams
Id jugador: 1629121
Id equipo: 1610612749
Claro está que si el nombre de la clave no coincide con el de la propiedad, tendrás una excepción NoSuchElementException
. Y si el tipo de los valores difiere, será una ClassCastException
.
Delegar A Mapa Mutable
Claro está que las propiedades mutables deben delegar a instancias de MutableMap
para cubrir la modificación de su valor. Esto permitirá dirigir el valor asignado a las propiedades hacia mapa delegado si así lo deseas.
La convención de la delegación es posible, porque MutableMap
tiene definido el operador setValue()
para confiarle la lógica de los setters en las propiedades delegadas.
Ejemplo:
A partir de un mapa mutable que contiene el perfil de un usuario, inicializar una variable que almacene el nick y lo muestre.
fun main() {
val userProfile = loadUserProfile()
val displayName by userProfile
println("displayName es $displayName")
userProfile["displayName"] = "ProtosWin"
println("displayName es $displayName")
}
private fun loadUserProfile() = mutableMapOf(
"displayName" to "Killer123",
"avatar" to "avatar_22",
"language" to "es"
)
Salida:
displayName es Killer123
displayName es ProtosWin
En este ejemplo tenemos la variable inmutable local displayName
. Variable que delega su valor al mapa userProfile
construido a partir de loadUserProfile()
.
Como puede observar, el valor inicial para la clave "displayName"
es "Killer123"
. Este se entrega a la variable displayName
sin problemas, ya que el nombre de la propiedad coincide con la clave.
Luego modificamos el valor por "ProtosWin"
e imprimimos de nuevo el valor de displayName
corroborando que su valor ha sido modificado, incluso si es val
.
Por otro lado, si deseas una modificación bidireccional entre propiedad y mapa, entonces declara la propiedad como var
. Al modificarla el mapa también modificará el valor del par asociado.
fun main() {
val userProfile = loadUserProfile()
// Propiedad var y mapa mutable
println("userProfile[\"language\"] -> ${userProfile["language"]}")
var language by userProfile
language = "en"
println("userProfile[\"language\"] -> ${userProfile["language"]}")
}
Salida:
userProfile["language"] -> es
userProfile["language"] -> en
Al asignar el valor "en"
a language
, el valor del par será mutado al nuevo estado como se ve en la impresión.
Ú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!