Clase de datos o data class en Kotlin

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

Entradas populares

Recursos gratis para aprender Kotlin

I/O: entrada y salida de datos en consola

Lectura y escritura de archivos