ProgramaciónDesarrollador de Kotlin

¿Cómo funcionan los Data Objects (data object) en Kotlin, para qué sirven, cómo se implementan equals/hashCode/toString, y en qué se diferencian de los objetos normales y de los data class?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Historia del tema:

Antes de Kotlin 1.9, los objetos object no podían ser data; no podías tener un singleton que obtuviera automáticamente equals, hashCode, toString, como los data classes. Con la aparición de data object, esta limitación se eliminó. Ahora puedes crear un objeto singleton con métodos auto-generados, adecuado para patrones Value y Enum-like.

Problema:

Anteriormente, para obtener un equals(), hashCode(), toString() correctos incluso para los objetos singleton, había que implementarlos manualmente o usar otros trucos, lo que aumentaba el BOILERPLATE y la posibilidad de error.

Solución:

Utiliza data object para objetos cuya instancia es única, y al mismo tiempo se requiere un comportamiento estándar de equals/hashCode/toString para pasar a colecciones, serialización, comparación y depuración.

Ejemplo de código:

data object NotAvailable fun checkStatus(status: Any) = when (status) { NotAvailable -> "Los datos están ausentes" else -> "Otro estado" } val set = setOf(NotAvailable) println(NotAvailable in set) // true println(NotAvailable.toString()) // NotAvailable

Características clave:

  • Data object implementa equals/hashCode/toString según el contrato de data class
  • Es un objeto singleton (una única instancia)
  • Adecuado para patrones value-like o enum-like sin datos

Preguntas con trampa.

¿Pueden los data object contener propiedades?

Sí, pero solo propiedades val sin backing field (ya que no se debe almacenar nada en un singleton)

data object Loading { val status: String get() = "Cargando..." }

¿En qué se diferencia un data object de un objeto normal en términos de equals?

El equals de un objeto normal verifica solo la identidad de referencia, mientras que en el data object se compara el contrato de datos, pero en el caso de un singleton, siempre es el mismo objeto. Sin embargo, el equals/hashCode sobreescrito es más útil para colecciones.

¿Se puede hacer herencia de un data object?

No, data object es final, al igual que cualquier objeto en Kotlin; no se puede heredar.

Errores típicos y anti-patrones

  • Usar data object en lugar de enum cuando hay varios objetos
  • Usar data object intentando almacenar datos — no está permitido
  • No tener en cuenta que la igualdad siempre es por referencia, aunque se considera por valor en colecciones

Ejemplo de la vida real

Caso negativo

En lugar de enum para todos los estados, se usaron diferentes data object. Un año después, se necesitó serialización por nombres, y se empezaron a emparejar manualmente los nombres de los objetos con tipos.

Pros:

  • Inicialización fácil

Contras:

  • Costuras adicionales para la serialización, error en el emparejamiento

Caso positivo

Para el valor de retorno de una solicitud de red, se utilizaron data object para estados especiales: Loading, Empty, Error. Así, el código es compacto, y la soporte para equals, hashCode, toString es automático.

Pros:

  • Conveniente para comprobar en colecciones
  • Bonito registro

Contras:

  • No se pueden agregar propiedades variables, solo val-lazy