In Scala there exist the construct of a ‘case class’. According to Martin Odersky this supports you to write a “regular, non-encapsulated data structure”. It always seems to be associated with pattern matching.
So when to use a case class and when to use a ‘plain’ class?
I found this nice explanation stating:
“Case classes can be seen as plain and immutable data-holding objects that should exclusively depend on their constructor arguments.
This functional concept allows us to
- use a compact initialisation syntax (Node(1, Leaf(2), None)))
- decompose them using pattern matching
- have equality comparisons implicitly defined
In combination with inheritance, case classes are used to mimic algebraic datatypes.
If an object performs stateful computations on the inside or exhibits other kinds of complex behaviour, it should be an ordinary class.“
Defining a case class gives you a lot of boilerplate code for free:
- Getters are generated for the constructor parameters. Setters are only generated when the parameters are declared as var. They are val by default.
- A nice toString method is generated.
- An equals and hashCode methods are generated.
- A copy method is generated to clone an object.
- An apply method is generated, removing the need to use the new keyword when creating a new instance of the class.
- An unapply method is generated.
Test it out by starting the Scala repl in a terminal:
Welcome to Scala version 2.11.4 (Java HotSpot(TM) Client VM, Java 1.7.0_75).
Type in expressions to have them evaluated.
Type :help for more information.
scala> case class Camera(brand: String, model: String)
defined class Camera
scala> val myCamera = Camera("Canon", "5D Mark III")
myCamera: Camera = Camera(Canon,5D Mark III)
If you type in the name of your object with a ‘.’ and press tab, the repl will display some of the available methods that are generated.
asInstanceOf brand canEqual copy isInstanceOf model productArity productElement productIterator productPrefix toString
Alvin Alexander writes that case classes are primarily intended to create “immutable records” that you can easily use in pattern matching expressions.
So while you can define the constructor parameters as var, they are intended to be val.