Computing is all about logic and data. Various languages provide different ways to handle data. Primitive data types like Int, String and Boolean are usually never enough to represent anything meaningful by themselves. For example – If we were to capture the details of a Person – it will consist of many attributes. First Name, Last Name, Age, email Id etc. The real-world data is more complex and is made up of different primitive data types.
Scala provides a clean way of putting and aggregating all this data together into immutable structures called case classes. Case classes are defined as normal classes except the definition is pre-fixed by a modifier case.
Case classes provide a lot of boilerplate code, which reduces the amount of code which needs to be written to handle complex aggregated data. Cases classes are also very useful in pattern matching and if you are working with Spark data sets.
Let’s try and a simple case class and try and see what it brings to the table. See Below
val p1 = new Person ("John","Doe",20,"[email protected]")
val p2 = new Person("Tim","Cole",25,"[email protected]")
//Prints Person(John,Doe,20,[email protected])
println(p1)
In languages like Java, the developer would need to add getters amongst others. But in Scala the compiler takes care of the requirement of adding the boilerplate code for getters. Keep in mind that case classes are immutable objects so there are no setters. In addition, to getters there are additional methods which are added – toString, copy, equals, hashCode.
Let’s see how these functions work
toString provides a string representation. See below
age: Int, emailId:String)
val p1 = new Person ("John","Doe",20,"[email protected]")
val p2 = new Person("Tim","Cole",25,"[email protected]")
//Prints Person(John,Doe,20,[email protected])
println(p1.toString)
Observe that the output of p1.toString is different from when you print p1. One is an object the other is a string.
copy provides a way to copy the case class and assign it to another value. In addition to that(which is not a big deal) it provides a way to change the value of the primitive types contained inside the case clases. This is useful as case classes are immutable.
age: Int, emailId:String)
val p1 = new Person ("John","Doe",20,"[email protected]")
val p2 = new Person("Tim","Cole",25,"[email protected]")
val p3 = p1.copy(firstName = "Jane")
//Prints Person(Jane,Doe,20,[email protected])
println(p3.toString)
equals is a function which can be used to compare two case classes. When comparing case classes – Scala checks the class, structure along with the values.
age: Int, emailId:String)
case class XPerson(firstName: String, lastName: String,
age: Int, emailId:String)
val p1 = new Person ("John","Doe",20,"[email protected]")
val p2 = new Person ("Tim","Cole",25,"[email protected]")
val p3 = new Person ("John","Doe",20,"[email protected]")
val p4 = new XPerson ("Tim","Cole",25,"[email protected]")
//Prints true
println(p3.equals(p1))
//Prints false
println(p4.equals(p2))
This approach is different from the approach in Java. where two objects are equal when they point to the same instance in the memory. This can be proven using the hashCode method which returns an integer for the object. In Scala, the behaviour is a bit different it returns the same integer if the class, structure along with the values are same.
Before we close this entry let’s see how we can unpack a case class object into individual elements. See Below
Elements of Person case class are now available as individual values and can be used as such.
No discussion of case class would be complete without discussing pattern matching in Scala. Pattern matching coming up next!