English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Classe dati (Data) in Kotlin

In questo articolo, imparerai a creare classi dati in Kotlin. Inoltre, imparerai le richieste che devono soddisfare le classi dati e le loro funzionalità standard.

Può verificarsi una situazione del genere: hai bisogno di creare una classe utilizzata solo per salvare dati. In questo caso, puoi marcare la classe come data per creare una classe dati. Ad esempio:

data class Person(val name: String, var age: Int)

Per questo tipo, il compilatore genera automaticamente:

  • Funzione copy(), equals() e hashCode() e la forma toString() del costruttore principale

  • Funzione componentN()

Prima di discutere in dettaglio queste funzioni, parliamo delle richieste che devono soddisfare le classi dati.

Richieste delle classi dati in Kotlin

Richieste come segue:

  • Il costruttore principale deve avere almeno un parametro.

  • I parametri del costruttore principale devono essere marcati come val (solo lettura) o var (lettura e scrittura).

  • La classe non può essere aperta, astratta, interna o sigillata.

  • La classe può estendere altre classi o implementare interfacce. Se si utilizza una versione di Kotlin 1.1 o precedente, la classe può implementare solo interfacce.

Esempio: utilizzo delle classi dati in Kotlin

data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
    val jack = User("jack", 29)
    println("name = ${jack.name}")
    println("age = ${jack.age}")
}

Quando si esegue il programma, l'output è:

name = jack
age = 29

Quando si dichiara una classe dati, il compilatore genera automaticamente alcune funzioni in background, come toString(), equals(), hashcode() ecc., il che aiuta a mantenere la semplicità del codice. Se si utilizza Java, è necessario scrivere molto codice di esempio.
Usiamo le seguenti funzioni:

Funzione copy() - copia

Per i dati delle classi, è possibile utilizzare la funzione copy() per creare copie di oggetti con proprietà diverse. Il suo meccanismo di funzionamento è il seguente:

data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
    val u1 = User("John", 29)
   
    // Creazione di un oggetto utilizzando la funzione di copia
    val u2 = u1.copy(name = "Randy")
    println("u1: name = ${u1.name}, name = ${u1.age}")
    println("u2: name = ${u2.name}, name = ${u2.age}")
}

Quando si esegue il programma, l'output è:

u1: name = John, name = 29
u2: name = Randy, name = 29

Metodo toString() - restituzione di una stringa

La funzione toString() restituisce la rappresentazione in stringa dell'oggetto.

data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
    val u1 = User("John", 29)
    println(u1.toString())
}

Quando si esegue il programma, l'output è:

User(name=John, age=29)

hashCode() e equals()

Il metodo hashCode() restituisce il codice hash dell'oggetto. Se due oggetti sono uguali, hashCode() genererà lo stesso risultato numerico.

Se due oggetti sono uguali (hashCode() è lo stesso), equals() restituisce true. Se gli oggetti non sono uguali, equals() restituisce false.

data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
    val u1 = User("John", 29)
    val u2 = u1.copy()
    val u3 = u1.copy(name = "Amanda")
    println("u1 hashCode = ${u1.hashCode()}")
    println("u2 hashCode = ${u2.hashCode()}")
    println("u3 hashCode = ${u3.hashCode()}")
    if (u1.equals(u2) == true)
        println("u1 è uguale a u2.")
    else
        println("u1 non è uguale a u2.")
    if (u1.equals(u3) == true)
        println("u1 è uguale a u3.")
    else
        println("u1 non è uguale a u3.")
}

Quando si esegue il programma, l'output è:

u1 hashCode = 71750738
u2 hashCode = 71750738
u3 hashCode = 771732263
u1 è uguale a u2.
u1 non è uguale a u3.

Dichiarazione di destrutturazione

Puoi utilizzare la dichiarazione di destrutturazione per decomporre un oggetto in più variabili. Ad esempio:

data class User(val name: String, val age: Int, val gender: String)
fun main(args: Array<String>) {
    val u1 = User("John", 29, "Maschio")
    val (name, age, gender) = u1
    println("name = $name")
    println("age = $age")
    println("gender = $gender")
}

Quando si esegue il programma, l'output è:

name = John
age = 29
gender = Male

Questo è possibile perché il compilatore genera automaticamente la funzione component() per tutti gli attributi della classe dati. Ad esempio:

data class User(val name: String, val age: Int, val gender: String)
fun main(args: Array<String>) {
    val u1 = User("John", 29, "Maschio")
    println(u1.component1())     // John
    println(u1.component2())     // 29  
    println(u1.component3())     // "Maschio"
}

Quando si esegue il programma, l'output è:

John
29
Maschio