Data classes

Data classes are one more concept that Kotlin uses to be a more productive language. To show this, let's go back to our User class in Java. If we wanted to compare this type by the values it holds (its properties), we would have to override the equals method and compare all the values inside it. But then, with the equals method overridden, we also have to override the hashcode method; otherwise, none of the hash-related collection types (HashMap, HashSet, HashTable, and so on) would work. The hashcode method should return an equal hash value from all objects that the equals method considers the same. While we are overriding those two methods, let's also override the toString method so that the users of our class can get a nice string representation of it. Then, the Java version would look like this (getter and setter methods omitted):

public final class User {
private String firstName;
private String lastName;
private int birthYear;

public User(String firstName, String lastName, int birthYear) {
this.firstName = firstName;
this.lastName = lastName;
this.birthYear = birthYear;
}

@Override
public boolean equals(Object obj) {
if (obj instanceof User) {
User other = (User)obj;
return this.firstName.equals(other.firstName)
&& this.lastName.equals(other.lastName)
&& this.birthYear == other.birthYear;
}
return false;
}

@Override
public int hashCode() {
int result = 31;
result = 31 * result + this.firstName.hashCode();
result = 31 * result + this.lastName.hashCode();
result = 31 * result + birthYear;
return result;
}

@Override
public String toString() {
return "User(firstName="+this.firstName
+ ", lastName=" + this.lastName
+ ", birthYear=" + this.birthYear
+ ")";
}
}

But in Kotlin, thanks to data classes, the equivalent code would look like this:

data class User(var firstName: String,
var lastName: String,
var birthYear: String)

Again, if we didn't break the lines for readability, the Kotlin code could be only one line. And yes, only adding the data keyword in front of the class will tell the Kotlin compiler to produce in the bytecode all the code we had to type in the Java version.

When you declare a data class, the compiler implements the hashcode, equals, and toString functions for you. It also adds one more that we don't have in our Java version. That is the copy function. Sometimes, there is a need to get a copy of an object and at the same time modify some of its properties. If we wanted to copy our user and change only his first name, we'd do it like this:

val user = User("Bruce", "Wayne", "1965")
val userCopy = user.copy("John")

This code will produce a compiler warning. The copy function should use named arguments (we'll learn about them in the next chapter). The proper way would be to specify the name of the argument we are changing, like this:

val user = User("Bruce", "Wayne", "1965")
val userCopy = user.copy(firstName = "John")

By default, the Kotlin compiler will generate all the functions we have mentioned. But if you want to have your own version of any of these functions, you just have to implement it yourself in your data class. When the compiler sees that you overrode such a method, it'll skip adding it and the one you've provided will be used.

Finally, we have to mention the restrictions on using data classes:

  • It cannot be an open, sealed, or abstract class
  • The primary constructor parameters have to be properties, that is, they have to have the val or var keyword
  • The primary constructor has to have at least one property
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.161.132