Main use of data class
is to ease the work of writing POJOs.
If you get into the IDE and write your VideoGame
class:
data class VideoGame(val name: String, val publisher: String, var reviewScore: Int)
And then you de-compile it:
Your IDE Toolbar > Tools > Kotlin > Show Kotlin bytecode > Decompile
You get this:
@Metadata(
mv = {1, 1, 16},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000\"\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0002\n\u0002\u0010\b\n\u0002\b\r\n\u0002\u0010\u000b\n\u0002\b\u0004\b\u0086\b\u0018\u00002\u00020\u0001B\u001d\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0003\u0012\u0006\u0010\u0005\u001a\u00020\u0006¢\u0006\u0002\u0010\u0007J\t\u0010\u000f\u001a\u00020\u0003HÆ\u0003J\t\u0010\u0010\u001a\u00020\u0003HÆ\u0003J\t\u0010\u0011\u001a\u00020\u0006HÆ\u0003J'\u0010\u0012\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u00032\b\b\u0002\u0010\u0004\u001a\u00020\u00032\b\b\u0002\u0010\u0005\u001a\u00020\u0006HÆ\u0001J\u0013\u0010\u0013\u001a\u00020\u00142\b\u0010\u0015\u001a\u0004\u0018\u00010\u0001HÖ\u0003J\t\u0010\u0016\u001a\u00020\u0006HÖ\u0001J\t\u0010\u0017\u001a\u00020\u0003HÖ\u0001R\u0011\u0010\u0002\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\b\u0010\tR\u0011\u0010\u0004\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\n\u0010\tR\u001a\u0010\u0005\u001a\u00020\u0006X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u000b\u0010\f\"\u0004\b\r\u0010\u000e¨\u0006\u0018"},
d2 = {"Lcom/yourpackage/VideoGame;", "", "name", "", "publisher", "reviewScore", "", "(Ljava/lang/String;Ljava/lang/String;I)V", "getName", "()Ljava/lang/String;", "getPublisher", "getReviewScore", "()I", "setReviewScore", "(I)V", "component1", "component2", "component3", "copy", "equals", "", "other", "hashCode", "toString", "app"}
)
public final class VideoGame {
@NotNull
private final String name;
@NotNull
private final String publisher;
private int reviewScore;
@NotNull
public final String getName() {
return this.name;
}
@NotNull
public final String getPublisher() {
return this.publisher;
}
public final int getReviewScore() {
return this.reviewScore;
}
public final void setReviewScore(int var1) {
this.reviewScore = var1;
}
public VideoGame(@NotNull String name, @NotNull String publisher, int reviewScore) {
Intrinsics.checkParameterIsNotNull(name, "name");
Intrinsics.checkParameterIsNotNull(publisher, "publisher");
super();
this.name = name;
this.publisher = publisher;
this.reviewScore = reviewScore;
}
@NotNull
public final String component1() {
return this.name;
}
@NotNull
public final String component2() {
return this.publisher;
}
public final int component3() {
return this.reviewScore;
}
@NotNull
public final VideoGame copy(@NotNull String name, @NotNull String publisher, int reviewScore) {
Intrinsics.checkParameterIsNotNull(name, "name");
Intrinsics.checkParameterIsNotNull(publisher, "publisher");
return new VideoGame(name, publisher, reviewScore);
}
// $FF: synthetic method
public static VideoGame copy$default(VideoGame var0, String var1, String var2, int var3, int var4, Object var5) {
if ((var4 & 1) != 0) {
var1 = var0.name;
}
if ((var4 & 2) != 0) {
var2 = var0.publisher;
}
if ((var4 & 4) != 0) {
var3 = var0.reviewScore;
}
return var0.copy(var1, var2, var3);
}
@NotNull
public String toString() {
return "VideoGame(name=" + this.name + ", publisher=" + this.publisher + ", reviewScore=" + this.reviewScore + ")";
}
public int hashCode() {
String var10000 = this.name;
int var1 = (var10000 != null ? var10000.hashCode() : 0) * 31;
String var10001 = this.publisher;
return (var1 + (var10001 != null ? var10001.hashCode() : 0)) * 31 + this.reviewScore;
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof VideoGame) {
VideoGame var2 = (VideoGame)var1;
if (Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.publisher, var2.publisher) && this.reviewScore == var2.reviewScore) {
return true;
}
}
return false;
} else {
return true;
}
}
}
So the backing fields ARE private. Kotlin is doing all the tedious and heavy lifting for you. That is:
- Backing fields with getters and setters
- Basic implementation of
toString
- Implementation of
equals
- Implementation of
hashCode
- Annotating nullability
- Writing the constructor implementation
- Adding a useful
copy
method
You get a whoping 82 lines of bloated code that you maybe would've written yourself (maybe sprinkling some bugs in it?) in Java in exchange of 1 keyword. Isn't it awesome?
So quick recap
data class
make way easier writing POJOs
val
tells the compiler to implement a getter for a given property. That property is also going to be immutable within the class itself. (You can't change it in functions belonging to that class)
var
tells the compiler to provide setter and getters
- You can set the visibility of properties in the same
data class
like: data class MyClass(private val prop: Int)
Further examples:
The keywords that you are using infront of val and var only affect the visibility of the getters and setters.
For instance: Public get but private set:
class VideoGame {
var pegiRating: Int = 0
private set
}