En este tutorial, echaremos un vistazo a la Clase de Datos en Kotlin. Si no has leído el artículo sobre Clases en Kotlin, te recomendamos hacerlo antes de continuar.
Clase de Datos en Kotlin
¿Te cansas de escribir miles de líneas de código para tus clases de datos POJO en Java? Todo programador Java en algún momento debe haber tomado nota de la cantidad de líneas de código que necesita escribir para clases que simplemente deben almacenar algunos datos. Veamos cómo se ve una clase POJO
Book.java
:
public class Book {
private String name;
private String authorName;
private long lastModifiedTimeStamp;
private float rating;
private int downloads;
public Book(String name, String authorName, long lastModified, float rating, int downloads) {
this.name = name;
this.authorName = authorName;
this.lastModifiedTimeStamp = lastModified;
this.rating = rating;
this.downloads = downloads;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public long getLastModifiedTimeStamp() {
return lastModifiedTimeStamp;
}
public void setLastModifiedTimeStamp(long lastModifiedTimeStamp) {
this.lastModifiedTimeStamp = lastModifiedTimeStamp;
}
public float getRating() {
return rating;
}
public void setRating(float rating) {
this.rating = rating;
}
public int getDownloads() {
return downloads;
}
public void setDownloads(int downloads) {
this.downloads = downloads;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book that = (Book) o;
if (downloads != that.downloads)
return false;
if (name != null ? !name.equals(that.name) :
that.name != null) {
return false;
}
return authorName != null ?
authorName.equals(that.authorName) :
that.authorName == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (authorName != null ?
authorName.hashCode() : 0);
result = 31 * result + downloads;
return result;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + authorName + '\'' +
", lastModifiedTimestamp='" + lastModifiedTimeStamp + '\'' +
", rating='" + rating + '\'' +
", downloads=" + downloads +
'}';
}
}
¡Vaya! ¡Eso son 96 líneas de código solo para almacenar 5 campos en un objeto! Aquí no estamos haciendo mucho más que tener métodos getter, setter, toString()
, equals()
y hashCode()
. Con las arquitecturas limpias y las prácticas de separación de código en nuestras prácticas, necesitamos crear clases POJO ya que cada proyecto necesita almacenar datos en algún lugar. Esto puede aumentar el código de relleno. Aquí es donde Kotlin viene al rescate, con el uso de las Clases de Datos. Las Clases de Datos son la respuesta de Kotlin para reducir el código de relleno. La clase POJO anterior se puede escribir en Kotlin de la siguiente manera:
data class Book(var name: String, var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)
¡ES TODO. Kotlin convierte un código java de 96 líneas en una sola línea de código. ¡Esta es la forma de Kotlin de reducir el código de relleno en tu proyecto!
Creación de la clase de datos Kotlin
A continuación se presentan los requisitos para crear una clase de datos Kotlin.
- Debe agregar la palabra clave
data
a la clase. - El constructor principal debe tener al menos un parámetro.
- Cada parámetro del constructor principal debe tener asignado un
val
o unvar
. Esto no es necesario en una clase normal, donde especificar unval
o unvar
no es obligatorio. - Las clases de datos no pueden tener las palabras clave
abstract
,open
,sealed
oinner
.
Métodos integrados de la clase de datos Kotlin
La clase de datos Kotlin crea automáticamente las siguientes funciones para ti.
equals()
yhashCode()
toString()
en forma de"Libro(nombre=JournalDev, autor=Anupam)"
- Funciones
componentN()
para cada uno de los parámetros en el orden especificado. Esto se conoce como declaraciones de desestructuración. copy()
Características de las Clases de Datos de Kotlin
A continuación se presentan algunas características que proporciona una Clase de Datos.
-
Para crear un constructor sin parámetros, especifique valores predeterminados para cada uno de los parámetros presentes en el constructor primario.
-
Una Clase de Datos permite la subclase (no es necesario mencionar la palabra clave
open
). -
Puede proporcionar implementaciones explícitas para las funciones
equals()
,hashCode()
ytoString()
. -
No se permiten implementaciones explícitas para las funciones
copy()
ycomponentN()
. -
Podemos controlar la visibilidad de los getters y setters especificando los modificadores de visibilidad en el constructor como se muestra a continuación.
data class Libro(var nombre: String, private var nombreAutor: String, var ultimaModificacion: Long, var calificacion: Float, var descargas: Int)
-
Un parámetro val no tendrá un setter definido implícitamente (¡tampoco se puede hacer explícitamente!).
Argumentos Predeterminados y Nombrados en Clases de Datos
A continuación se muestra nuestra clase de datos:
data class Book(var name: String, var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)
Ninguno de los parámetros tiene un valor predeterminado establecido. Por lo tanto, necesitamos establecer un argumento para cada uno de ellos en la instanciación como se muestra a continuación.
fun main(args: Array<String>) {
val book = Book("Android Tutorials","Anupam", 1234567, 4.5f, 1000)
}
Establezcamos algunos argumentos predeterminados y veamos cómo cambia la instanciación.
data class Book(var name: String, var authorName: String = "Anupam", var lastModified: Long = 1234567, var rating: Float = 5f, var downloads: Int = 1000)
fun main(args: Array<String>) {
var book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
book = Book("Kotlin")
book = Book("Swift",downloads = 500)
book = Book("Java","Pankaj",rating = 5f, downloads = 1000)
book = Book("Python","Shubham",rating = 5f)
}
En lugar de establecer cada argumento, podemos establecer solo los que no son predeterminados y aquellos que deseemos usando el argumento nombrado. Usando los Argumentos Nombrados, podemos establecer el quinto argumento como el segundo especificando explícitamente el nombre del parámetro seguido de =
. ¡La vida es mucho más fácil de esta manera!
Método toString() de la Clase de Datos en Kotlin
El método toString() se crea implícitamente e imprime los nombres y etiquetas de los argumentos para la instancia como se muestra a continuación.
data class Book(var name: String, var authorName: String = "Anupam", var lastModified: Long = 1234567, var rating: Float = 5f, var downloads: Int = 1000)
fun main(args: Array) {
var book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
println(book)
book = Book("Kotlin")
println(book)
book = Book("Swift",downloads = 500)
println(book)
book = Book("Java","Pankaj",rating = 5f, downloads = 1000)
println(book.toString())
book = Book("Python","Shubham",rating = 5f)
println(book.toString())
}
//Lo siguiente se imprime en la consola.
//Libro(nombre=Tutoriales de Android, autor=Anupam, últimaModificación=1234567, calificación=4.5, descargas=1000)
//Libro(nombre=Kotlin, autor=Anupam, últimaModificación=1234567, calificación=5.0, descargas=1000)
//Libro(nombre=Swift, autor=Anupam, últimaModificación=1234567, calificación=5.0, descargas=500)
//Libro(nombre=Java, autor=Pankaj, últimaModificación=1234567, calificación=5.0, descargas=1000)
//Libro(nombre=Python, autor=Shubham, últimaModificación=1234567, calificación=5.0, descargas=1000)
Nota: La función print
agrega implícitamente un toString().
Método copy() de la Clase de Datos de Kotlin
La función Copy se utiliza para crear una copia de una instancia de la clase de datos con algunas de las propiedades modificadas. Se recomienda utilizar parámetros val en el constructor de las clases de datos para utilizar propiedades inmutables de las instancias. Los objetos inmutables son más fáciles de manejar en aplicaciones con subprocesos múltiples. Por lo tanto, para crear una copia de un objeto inmutable cambiando solo algunas de las propiedades, la función copy()
es útil.
data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
println(book)
val newBook = book.copy(name = "Kotlin")
println(newBook)
}
//Lo siguiente se imprime en la consola.
//Libro(nombre=Tutoriales de Android, autor=Anupam, últimaModificación=1234567, calificación=4.5, descargas=1000)
//Libro(nombre=Kotlin, autor=Anupam, últimaModificación=1234567, calificación=4.5, descargas=1000)
Clase de Datos Kotlin equals() y hashCode()
El método hashCode()
devuelve el código hash para el objeto. Si dos objetos son iguales, hashCode()
produce el mismo resultado entero. Por lo tanto, equals()
devuelve true si el hashCode()
es igual, de lo contrario devuelve false.
data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
println("Hashcode is ${book.hashCode()}")
val newBook = book.copy(name = "Kotlin")
println("Hashcode is ${newBook.hashCode()}")
val copyBook = book.copy()
println("Hashcode is ${copyBook.hashCode()}")
if(copyBook.equals(book))
println("copyBook and book are equal")
if(!book.equals(newBook))
println("newBook and book are NOT equal")
}
//Lo siguiente se imprime en la consola.
//Hashcode es 649213087
//Hashcode es 1237165820
//Hashcode es 649213087
//copyBook y book son iguales
//newBook y book NO son iguales
Los códigos hash del primer y tercer objeto son iguales, por lo tanto, son iguales. Nota: El método equals()
es equivalente a ==
en Kotlin.
Declaraciones de Desestructuración
La función componentN()
nos permite acceder a cada uno de los argumentos especificados en el constructor, en el orden especificado. N es el número de parámetros en el constructor.
data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array<String>) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
println(book.component1()) //Android tutorials
println(book.component2()) //Anupam
println(book.component3()) //1234567
println(book.component4()) //4.5
println(book.component5()) //1000
}
Las declaraciones de desestructuración nos permiten acceder a los argumentos como propiedades del objeto de la clase, como se muestra a continuación.
data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array<String>) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
val (n,a,date,rating,downloads) = book
}
Nota: Si se establece un modificador de visibilidad como privado en alguno de los argumentos, no se puede acceder en la función anterior.
data class Book(val name: String,private val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array<String>) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
val (n,a,date,rating,downloads) = book //This won't compile since authorName is private
}
Eso es todo para un resumen rápido sobre las Clases de Datos en Kotlin. Referencias: Documentación de Kotlin
Source:
https://www.digitalocean.com/community/tutorials/kotlin-data-class