If you’ve done Python before, a case class in Scala is similar to collections.namedtuple and data classes (available only in Python 3.7+). These are all tools used commonly to model immutable structured data.
It’s a thin abstraction over a normal class, with a constructor used to assign values to named fields. Here is a simple example of a case class in Scala.
scala> case class Person(name: String, email: String, age: Int)
defined class Person
scala> val bob = Person("Bob", "bob@me.com", 24)
bob: Person = Person(Bob,bob@me.com,24)
scala> Person(age = 24, name = "Bob", email = "bob@me.com")
res0: Person = Person(Bob,bob@me.com,24)
The same class expressed as a namedtuple:
from collections import namedtuple
Person = namedtuple("Person", ["name", "email", "age"])
bob = Person("bob", "bob@me.com", 24)
or as a data class (note the frozen=True
parameter to more closely mimic the
immutability aspect of the other two):
from dataclasses import dataclass
@dataclass(frozen=True)
class Person:
name: str
email: str
age: int
bob = Person("bob", "bob@me.com", 24)
#Pattern matching
The immutability aspect of case classes makes it possible to do certain operations more naturally than just plain Scala classes.
Equality
Comparisons between instances of case classes are done by value, not by reference.
scala> val bob = Person("Bob", "bob@me.com", 24)
bob: Person = Person(Bob,bob@me.com,24)
scala> val bob2 = Person("Bob", "bob@me.com", 24)
bob2: Person = Person(Bob,bob@me.com,24)
scala> bob == bob2
res1: Boolean = true
Pattern matching
In particular, case classes support pattern matching:
scala> abstract class Animal
defined class Animal
scala> case class Person(name: String, email: String, age: Int) extends Animal
defined class Person
scala> case class Dog(name: String, age: Int) extends Animal
defined class Dog
scala> object Census {
| def check(a: Animal): String = a match {
| case Person("bob", _, _) => "Hey, it's Bob!"
| case Person(_, _, _) => "Hey, it's a person"
| case Dog(_, _) => "Woof!"
| }
| }
defined object Census
scala> val bob = Person("Bob", "bob@me.com", 24)
bob: Person = Person(Bob,bob@me.com,24)
scala> val andy = Person("Andy", "andy@me.com", 26)
andy: Person = Person(Andy,andy@me.com,26)
scala> val fluffball = Dog("fluffball", 2)
fluffball: Dog = Dog(fluffball,2)
scala> Census.check(bob)
res0: String = Hey, it's Bob!
scala> Census.check(andy)
res1: String = Hey, it's a person
scala> Test.check(fluffball)
res2: String = Woof!
This page will be updated with more information relevant to case classes as I delve deeper into the world of Scala!
More readings: