Data Classes in Kotlin
Data Classes in Kotlin

Kotlin Data Class is purpose-built to streamline operations related to data, providing default functionality and convenience methods for regular data-related tasks. Let’s begin our introduction to these classes in the Kotlin language by examining the requirements for their usage.

Data Classes in Kotlin

Kotlin Data Class is purpose-built to streamline operations related to data, providing default functionality and convenience methods for regular data-related tasks. Let’s begin our introduction to these classes in the Kotlin language by examining the requirements for their usage. 

Working with data classes is simple, but specific guidelines need to be adhered to:

  1. The class declaration must include the key “data”.
  2. The primary constructor must have a minimum of one parameter.
  3. Every parameter must be assigned “val” or “var”. However, this requirement does not apply to regular classes, where “val” and “var” are optional.
  4. It is not possible to declare data classes as abstract, open, sealed, or inner.
  5. Classes in Kotlin have the flexibility to extend other classes or implement interfaces, which means a class can inherit properties and behaviors from another class, allowing code reuse and promoting modularity.
  6. In Kotlin, data classes can have default values for their properties, which allows you to define initial values that use if no explicit value providing when creating an instance of the data class.

A basic example of a Kotlin Data Class is to showcase the Date on the screen in the format of month and day:

data class Date(val month: String, val day: Int)

fun main() {
    val today = Date("May", 23)
    println("month = ${today.month}")
    println("day = ${today.day}")
}

This code defines a data class named Date with two properties: month of type String and day of type Int. The class has a constructor that takes values for both properties.

In the main() function, an object named today of type Date is created with the values “May” for the month property and 23 for the day property.

Next, the values of the object’s properties print using the println() function. The string “month = ${today.month}” prints the value of the month property, and the string “day = ${today.day}” prints the value of the day property.

As a result, we will get the following:

month = May
day = 23

Therefore, this code creates an object of the Date class with values for the month and day and then prints these values to the screen.

After creating a class, the program automatically generates the necessary functions, which saves you from writing repetitive template code and simplifies typical operations related to data classes: Kotlin Data Class constructor, functions equals(), hashCode(), toString(), copy().

Fundamental operations

The compiler allows you to use several functions, significantly reducing the program code. Among them:

  • copy();
  • toString() method;
  • hashCode() та equals();
  • componentN().

In addition, when creating members of data classes, it is worth remembering the following:

  • If a class already provides custom implementations for functions such as equals(), hashCode(), or toString(), or if these functions marking as final in the superclass, the data class will not generate its implementations. Instead, it will use the existing implementations, ensuring consistency and preserving the intended behavior of these functions, allowing developers to have fine-grained control over the conduct of their data classes and avoid potential conflicts or unintended modifications.
  • If a supertype has open componentN() functions that return compatible types, for data class will generate corresponding functions that override those defined in the supertype. However, an error will occur if the program cannot override the supertype’s functions
  • It is not allowed to explicitly provide implementations for the componentN() and copy() functions.

Let’s consider everything in more detail.

Copy()

Kotlin Data Class copy functions allow you to create the desired objects by copying with some changed values:

data class Date(val month: String, val day: Int)

fun main() {
    val m1 = Date("May", 23)

    // using copy function to create an object
    val m2 = m1.copy(month = "June")

    println("m1: month = ${m1.month}, month = ${m1.day}")
    println("m2: month = ${m2.month}, month = ${m2.day}")
}

As a result, we will have:
m1: month = May, day = 23
m2: month = June, day = 23

toString() method

This function allows you to return the string type of the object:

data class Date(val month: String, val day: Int)

fun main() {
    val m1 = Date("May", 23)
    println(m1.toString())
}

On the screen, we will get the following:
Date(month=May, day=23)

hashCode() and equals()

The hashCode() function enables obtaining the hash code of a specific object. When two objects are considered equal, the hashCode() function consistently returns the same integer result. This property ensures that entities with the same content or characteristics produce matching hash codes, facilitating their proper categorization and efficient storage in data structures like hash maps or hash sets.

The Kotlin Data Class equals() function is one of the functions that the compiler automatically generates for data classes. The program uses this function to compare objects of the class based on the values of their properties.

The equals() function checks if two objects have the same values for each class property. If the values of all properties match, the function returns true, indicating that the objects are equal. Otherwise, if at least one property has a different value, the function returns false, indicating that the entities are unequal.

The basic implementation of the equals() function in a data class looks like this:

override fun equals(other: Any ? ): Boolean {
    if (this === other) return true
    if (other!is YourDataClass) return false

    return this.property1 == other.property1 &&
        this.property2 == other.property2 &&
        // Compare all necessary properties of the objects
        // ...
}

It’s important to note that the program automatically uses the equals() function when comparing data class objects using the == operator. For example:

val obj1 = YourDataClass("value1", 10)
val obj2 = YourDataClass("value1", 10)
 
println(obj1 == obj2) // Outputs: true

Since the compiler automatically generates the equals() function, you don’t need to write this function for a data class manually. Instead, the compiler ensures the correct implementation by comparing all the properties of the objects.

componentN() and destructuring declaration

In Kotlin, componentN() is a function automatically generated by the compiler for the properties of a data class. This function is associated with the Destructuring Declarations mechanism and allows the convenient unpacking of property values of a data class into individual variables.

Each property of the data class has its componentN() function, where N indicates the ordinal number of the property. For example, the program will generate component1() and component2() functions for a data class with two properties.

When using the destructuring declaration mechanism, you can assign the property values of a data class object to separate variables using a syntax similar to array assignment. For example:

val obj = YourDataClass("value1", 10)
val (prop1, prop2) = obj
 
println(prop1) // Outputs: value1
println(prop2) // Outputs: 10

In this example, the property values prop1 and prop2 will be unpacked from the obj object using the component1() and component2() functions.

The Kotlin compiler automatically generates the componentN() functions for the properties of a data class, enabling convenient usage of the destructuring declaration mechanism when working with data class objects, simplifying working with properties, and helping keep the code more understandable and concise.

FAQ

What is a data class in Kotlin?

In Kotlin, a data class is a special class type primarily used for holding and representing data. Its purpose is to simplify the process of creating classes that store data and provide basic functionality for working with that data.

Why use a data class Kotlin?

There are several compelling reasons for utilizing this class:

  • Automatic Generation of Common Functions.
  • Immutable by default.
  • Destructuring Declarations.
  • Copying Objects.
  • Convenient Property Access.
  • Interoperability with Libraries and Frameworks.

Overall, data classes in Kotlin are beneficial when dealing with data-centric applications, such as handling API responses, database records, or modeling domain objects.

How do I use data classes in Kotlin?

To use data classes in Kotlin, follow these steps: Declare a Data Class, Access and Modify Data, Utilize Generated Functions, and Destructuring Declarations.

You can customize data classes by adding additional functions, implementing interfaces, or extending other classes as needed.

What is the difference between a data class and a normal class in Kotlin?

Data classes in Kotlin are specifically designed for holding and manipulating data, providing default functionality for standard operations. In addition, they offer concise syntax, automatically generated functions, and support for destructuring declarations. 

Regular classes provide more flexibility and customization options but lack data classes’ default functionality.

What is a data class example?

An example of a data class could be a “Date” class that represents date information such as month, day, and year. Here’s an example:

data class Date(val month: String, val day: Int, val year: Int)

In this example, the data class “Date” has three properties: “month” of type String, “day” of type Int, and “year” of type Int.