Making a Case for Scala Case classes


If you are like me that is fed-up with writing or generating those getters / setters in your domain objects or Data Transfer Objects or Value Objects, defering the process of writing at compile time is definitely a boon. Scala's case classes does exactly that. Here are some of the noteworthy things to know about Scala case classes.

1. They are defined with the keyword case and are always immutable in nature because the parameters are val's implicitly!

case class Person(name: String, age: Int)
Now you could of course make the parameters var's, but be warned that your equals and hashCode behavior that you implicitly get is not bound to do what you wanted it to do

2. The parameters that are passed to the case classes are treated as final and are instantiated in the class constructor

3. Simple to instantiate and you could also define some defaults to the parameters if you do not want to supply them each and every time

case class Person(name: String = "MyName", age: Int)

val person = Person(29) // Would instantiate a person with name = MyName and age = 29

4. Gives you implicitly defined equals and hashCode implementation

5. You can decompose them using Scala's pattern matching feature, the reason you can pattern match a case class is because you also get the unapply method implemented for all your case classes

6. The getter methods are generated by default for you and if you have any var's as parameters, a setter method is also generated for that parameter that is declared as a var. But please don't try to mutate in a case class!

With all that said, let's now do a simple pattern matching snippet using a case classes:

abstract class Animal(age: Int)
case class Dog(name: String, age: Int) extends Animal(age)
case class Elephant(name: String, age: Int, sex: String) extends Animal(age)

We have now defined two case classes each with it's own set of properties. Here is a sample of the different scenarios and the results when trying to pattern match:

def patternMatchAnimal(animal: Animal) = animal match {
  case d: Dog => println("that was just Any Dog")
  case d: Dog("MyDog", _) => println("that was indeed My Dog")
  case e: Elephant(_, 100, _) => println("Wow! that elephant lived 100 years")
  case _ => println("Were you a human! well not really")
patternMatchAnimal(Dog("AnyDog", 2)) // prints -> that was just Any Dog
patternMatchAnimal(Dog("MyDog", 2))  // prints -> that was indeed My Dog
patternMatchAnimal(Elephant("Ele", 100, "M")) // prints -> Wow! that elephant lived 100 years
patternMatchAnimal(Elephant("Ele", 101, "M")) // prints -> Were you a human! well not really
Having said that, there is much more to case classes. Have a look at any Scala text to read more on Scala case classes!