Kotlin Data Classes

Kayvan Kaseb
Software Development
5 min readMar 20, 2020
Kotlin Data Classes

One of the main repetitive tasks in Java programming particularly in Android development with Java is creating Data Classes. In addition, the probability of occurring mistakes and bugs are high for programmers in the process of developing apps with Data Classes in Java. Fortunately, Kotlin as an advanced language has focused on this issue accurately and effectively. This essay aims to discuss the Data Class in Kotlin in order to diminish the amount of boilerplate code and enhance efficiency in developing applications.

What is a Data Class in Kotlin?

Fundamentally, Data Class is a simple class that is used to hold data or state, and includes standard functionality. This type of class just only contains state, and does not perform any kind of operations. Thus, a Data Class refers to a class, which contains only fields and crude methods for accessing them (getters and setters). Also, a data keyword is used to declare a class as a Data Class in Kotlin as below:

data class User(val name: String, val age: Int)

In fact, the reason why should you mention a class as data is to tell the compiler that you are creating this class for holding the data. So, the compiler creates several functions automatically for your Data Class, which could be useful for handling data. Data class includes the following built-in functions:

  1. equals(): Boolean

2. hashCode(): Int

3. toString(): String

4. copy()

5. componentN()

Some requirements for creating Kotlin Data Class

Following are rules and the requirements for implementing a Data Class in Kotlin:

  • The primary constructor of a Data Class needs to have at least one parameter.
  • Each parameter of the primary constructor must indicate as val or var.
  • Data classes cannot be marked as abstract, sealed, open, or inner.
  • This type of class can inherit another class, and it can implement an interface.

What is the problem in Java for creating a Data Class?

Although using Data Class is a significant issue, there is no best practice for making a difference among classes in Java. In other words, developers must recognize a Data Class just only due to structures and patterns that are indicated in codes. Essentially, the Java compiler observes these classes as other classes without any difference in appearance. Furthermore, implementing Data Classes is a widespread and repetitive task in programming especially in Android programming; therefore, the probability of occurring mistakes and bugs in creating these classes are high for developers. In Kotlin, the benefit of using Data Classes instead of common classes is that it gives us a massive amount of self-generated code, and eliminates a number of lines of codes as well.

An example for Java Data Class

Basically, if we want to create a class for Customer entry in Java, we usually create a class similar to following example, which needs an number of boilerplate codes only for three parameters:

public class Customer {      private String name;  
private int id;
private String city;

public Customer(String name, int id, String city) {

this.name = name;
this.id = id;
this.city = city;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Customer)) return false;
Customer customer = (Customer) obj;
return getId() == customer.getId() &&
Objects.equals(getName(), customer.getName()) &&
Objects.equals(getCity(), customer.getCity());
}

@Override
public int hashCode() {

return Objects.hash(getName(), getId(), getCity());
}

@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", id=" + id +
", city='" + city + '\'' +
'}';
}
}

To rewrite the above example in Kotlin, we can create it in a single line of code as follows:

data class Customer(var name: String, var id: Int, var city: String)

toString() method in Data Class

This method returns a string of all the parameters defined in the data class. For instance, toString() method calls implicitly in below example:

data class Customer(var name: String, var id: Int)  

fun main(agrs: Array<String>) {

val customer = Customer("John", 1122)
println(customer)//Output: Customer(name=John, id=1122)
}

An important point is that if we want to write this function without being a Data class, it shows the hashCode() with class name of Customer, which means it does not print the data.

equals() and hashCode() methods in Data Class

The hashCode() method returns hash code for the object. If two objects are equal, hashCode() generates the same integer result. Therefore, equals() returns true if the hashCode() is equal, else it returns false in output. For example:

data class Customer(var name: String, var id: Int)  

fun main(agrs: Array<String>) {
val firstObject = Customer("John", 1122)
val secondObject = Customer("Patrick", 1245)
println(firstObject == secondObject) // Output: true
println(firstObject.equals(secondObject)) // Output: true
}

If we want to write this function without being a Data class, it prints false for each of them because the firstObject and secondObject have different references.

copy() method in Data Class

Copy() method is used to create a copy or colon of an object in the data class. So, you can be able to modify some or all properties of an object. It is suggested to apply val parameters in a data classes constructor in order to use immutable properties of an object. Immutable objects are easier when you want to work with multi-threaded applications.

data class Customer(var name: String, var id: Int)  

fun main(agrs: Array<String>) {
val sampleObject = Customer("John", 1122)
println(sampleObject)
val copyObject = sampleObject.copy()
println(copyObject)

}

componentN() method for Destructuring Declarations in Data Class

componentN() function allows us access each of the arguments specified in the constructor in the order specified. N is defined as the number of parameters in the constructor.

data class Customer(var name: String, var id: Int)fun main(agrs: Array<String>) {val sampleObject = Customer("John", 1122)  
println(customer.component1()) //John
println(customer.component2()) //1122

}

Basically, Destructuring Declarations allows us to access the arguments as properties from the class. As a result, you can use each of the properties independently.

In conclusion, as we know, the probability of occurring bugs are high for programmers in the process of developing with Data Classes in developing Android apps with Java. Fortunately, Kotlin Data Class has solved the problem effectively, and decrease the amount of boilerplate code. In this essay is discussed the Data Class in Kotlin in some aspects.

--

--

Kayvan Kaseb
Software Development

Senior Android Developer, Technical Writer, Researcher, Artist, Founder of PURE SOFTWARE YAZILIM LİMİTED ŞİRKETİ https://www.linkedin.com/in/kayvan-kaseb