That’s not a secret that Scala is very popular programming language in BigData industry. And you may heard before that Scala is a data-centric programming language. This means not more, that with its help you can work with a data more easier comparing with other languages. Important roles in this play two Scala features: case classes and case objects.

An ideal data class is a case class

In any sort of applications we use some entities for representation of data or for a data transferring. Making a parallel with Java I can mention so called POJOs, DTO, VO etc. Imagine a class where you need to declare all required fields then constructors and finally the most painful stuff – getters and setters. A lot of boilerplate code, isn’t it?

Scala has extremely efficient alternative for this situations – case classes. What is a case class and what advantages does it has? Let’s start from the example:

case class Book(title: String, pages: Int)

What is hidden behind this line of code?

1) Class with 2 immutable fields
2) Getters for the fields
3) Constructor
4) Useful methods (will talk about that later)

Now let’s see how we can operate with the Book case class.

val b1 = Book("Scala book", 150)

b1.title //Scala book
b1.pages //150

val b2 = b1.copy(pages = 220)
b2.title //Scala book
b2.pages //220

b1.productArity //2
b1.productPrefix //Book
b1.productElement(0) //Scala book
b1.productElement(1) //150

b1.eq(b2) //false
b1.eq(Book("Scala book", 150)) //false
b1.equals(Book("Scala book", 150)) //true
b1 == b2 //false
b1 == Book("Scala book", 150) //true
By comparing case classes with help of == you check that each value inside of the first one class equals to the value of the second one class. One more point to a data-centric basket.

I’d like to emphasize the copy method. With its help you can create updated versions of a case class instance and change only that fields which you want. This is true Scala style – immutability. So by default all fields can’t be changed.

If you want mutable fields in a case class, I could do the following declaration:


As you see with help of the var keyword we can make any field mutable. In some use cases this can be helpful, but keep in mind that immutable values are less error prone for concurrent code.

Of course you can use a regular Scala classes to implement the same functionality which case classes provide. But this will be wasting of time.

Also you can set a default value for any parameter in a case class:

case class Ticket(title: String, priority: Int = 1)

res0: Ticket = Ticket(Localization,1)

In this example we set default value for the priority.

Companion objects

When you want to define some functionality related to a case class you have two possible ways to do this. The first one is to create functions directly in the case class.

case class Rectangle(length: Int = 0, width: Int = 0) {
    def square = length * width

But Scala suggests another place for a logic related to any case class. It’s a companion object. If a case class is a data holder, then a corresponding companion object is a service for this case class. Let’s look at code:

case class Rectangle(length: Int = 0, width: Int = 0)

object Rectangle {
  def square(rectangle: Rectangle) = rectangle.length * rectangle.width

val r1 = Rectangle(5, 4)

Note that in order to define a companion object for a class you have to set the same names for them and declare them in the same file.

As you see we defined the square function in the Rectangle object. Hence it can be applied for any Rectangle instance and what is more important – the data is separated from the logic.

About The Author

Mathematician, programmer, wrestler, last action hero... Java / Scala architect, trainer, entrepreneur, author of this blog