Case Class is one of the great tool introduced by Scala in the functional programming world.
Let’s explore what’s hidden behind the above class.
Case class is similar to a class but it provides a lot of boilerplate code for developers to use. By default, they are immutable i.e. once declared cannot be changed.
If we compile the case class using scalac command and decompile it using javap command, following code is generated:
Case classes automatically generate the following:
Getter methods for the constructor arguments.
Hashcode and equals.
Companion object with apply/unapply.
If a case class is a data holder, then a corresponding companion object is a service for that case class. Singleton object serves the purpose of both a factory and an extractor.
As a factory, it provides apply method which allows us to create an object without new keyword.
As an extractor, it provides unapply method which is used for pattern matching.
Case Class constructor parameters are promoted to members. Scala prefixes all the parameters with val. For vals only getters are provided.
We can change Case Class constructor parameters to vars. For vars getters and setters both are provided.
Case classes without parameters are meaningless and deprecated. In that situation, case objects are used.
Case objects can be created by simply calling the case object with empty parentheses which internally calls apply method and wherever we use the case class it refers to the companion object.
The copy method of case class allows full copy as well as copy using custom values.
equals method that does the comparison on basis of values.
The == also prints true and it is something called a synthetic method or bridge method which actually calls the equals method.
The eq method compares the memory address of the objects. The ne method is the exact opposite of eq.
hashCode method calls
scala.runtime.ScalaRunTime._hashCode which is defined as:
what you get is
elem1 * 41**n + elem2 * 41**(n-1) .. elemn * 1, where
n is the arity of case class and
elemi are the members of that case class.
Case classes use an algorithm called murmur hash and regular classes use the default hash. MurmurHash was chosen for Scala specifically because of measured defects in the simpler typical Java-style hash, and it has generally worked out well.
toString method in case classes does not give the hexadecimal representation of the hashcode rather it gives a meaningful representation of the class.
In the next blog, we will be discussing case class inheritance. Inheritance in case classes is difficult because of equals and hashcode methods.
Thanks for reading!