Clase de datos o data class en Kotlin
Es habitual crear una clase con el propósito principal de mantener o almacenar ciertos datos de los objetos de esa clase, y en estos casos se puede marcar la clase anteponiendo la palabra data para crear un tipo específico de clase conocida como clase de datos (data class):
data class Usuario(val nombre: String, val edad: Int)
Una data class no es más que una clase que sólo contiene estado y no realiza ninguna operación, y por tanto la utilizaremos cuando nos interese almacenar un conjunto de datos sin necesidad de implementar funcionalidades.
Para poder convertir una clase en una clase de datos es necesario que el constructor primario tenga al menos un parámetro (además todos los parámetros deben marcarse con val o var) y que la clase no tenga el modificador open, abstract, inner o sealed.
Para este tipo de clases, el compilador genera automáticamente algunas funciones aplicables a todas las propiedades declaradas en el constructor primario, como son equals, hashCode, toString, copy y componentN. Vamos a verlas en acción en el siguiente ejemplo:
// definimos una clase de datos con el modificador data data class Usuario(val nombre: String, val edad: Int) fun main() { val usuario1 = Usuario("Juan", 32) // la función toString() devuelve una representación String del objeto println(usuario1.toString()) // Usuario(nombre=Juan, edad=32) // toString() es invocado implícitamente por la función println() println(usuario1) // Usuario(nombre=Juan, edad=32) // la función copy sirve para crear nuevas instancias de la clase // a partir de las ya creadas val u1Update = usuario1.copy(edad = usuario1.edad + 1) println("${usuario1.nombre}, ${usuario1.edad}") // Juan, 32 println("${u1Update.nombre}, ${u1Update.edad}") // Juan, 33 // al copiar podemos cambiar el valor de las propiedades // utilizando los argumentos en el mismo orden que el constructor de la clase // o bien utilizando el nombre del argumento val otroUsuario = usuario1.copy() otroUsuario.copy("Pepe") otroUsuario.copy(edad = 12) // utilizamos copy para crear otros objetos val usuario2 = usuario1.copy() val usuario3 = usuario1.copy(nombre = "Felipe") // el método hashCode() devuelve un código del objeto // que será el mismo para objetos iguales println("${usuario1.hashCode()}") // 71922760 println("${usuario2.hashCode()}") // 71922760 println("${usuario3.hashCode()}") // 695271599 // equals() devuelve true si dos objetos son iguales (tienen el mismo hashCode()) // equals() considera dos instancias iguales si todas sus propiedades son iguales println("${usuario1 == usuario2}") // true println("${usuario1 == usuario3}") // false // las funciones de componenteN permiten obtener los valores // de las propiedades en el orden de declaración println(usuario1.component1()) // Juan println(usuario1.component2()) // 32 // no es necesario: // println("${usuario1.component2()}") // 32 // println(usuario1.component2().toString()) // 32 // println("${usuario1.component3()}") // ERROR // las funciones componente permiten la desestructuración de declaraciones val usuario4 = Usuario("Andrés", 25) val (nombreU4, edadU4) = usuario4 println("$nombreU4, $edadU4") // Andrés, 25 }
Recuerda que el compilador solo usa las propiedades definidas dentro del constructor primario para estas funciones generadas automáticamente, quedando excluidas las propiedades declaradas dentro del cuerpo de la clase. Así, en el siguiente ejemplo solo se tiene en cuenta la propiedad 'nombre' y se tratan como iguales dos objetos con el mismo 'nombre' pero diferentes 'edades':
data class Persona(val nombre: String) { var edad: Int = 0 } fun main() { val persona1 = Persona("Juan") val persona2 = Persona("Juan") persona1.edad = 22 persona2.edad = 33 println("${persona1 == persona2}") // true }
Comentarios
Publicar un comentario