Making a Case for Scala's case classes

Nitty gritty of the case class in Scala

joesan published on

3 min, 452 words

Categories: Technical Stuff

Tags: scala

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, deferring the process of writing at compile time is definitely a boon. Scala's case classes does exactly that. Some 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 parameter as var, but be warned that your equals and hashCode behavior that you implicitly get is not bound to do what you wanted it to do

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

  2. Simple to instantiate! 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
  1. Gives you implicitly defined equals and hashCode implementation

  2. 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

  3. 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 its own set of properties. Here is how pattern matching could then be applied:

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!