Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why shouldn't one use case classes exclusively?

Tags:

scala

Why shouldn't one use case classes exclusively ?

After all, they promote immutability, pattern matching over accessor methods etc ?

like image 410
Radu Stoenescu Avatar asked Jan 11 '16 10:01

Radu Stoenescu


1 Answers

People frequently use case classes and then try to customize/abuse them to do something else than what case classes are supposed to do.

E.g. if you want to

  • make some fields private
  • customize equality / hashCode
  • have mutable state
  • enforce invariants when constructing instances

you should use a normal class, even if you have to type a bit more.

Use a case class for pure, immutable and public data. Basically a tuple with named elements, nothing more. Use normal classes for e.g. handles to mutable resources (files, GUI controls etc.)

People frequently think that you can abuse case classes to do tasks reserved for normal classes. So here are a number of examples of misuse of case classes:

Private members

Members of a case class are never really private

case class Foo(x: Int, private val y: String)
val x = Foo(1, "Secret")
x.y // does not work, because y is private
x.productElement(1) // still does work
Foo.unapply(Foo(1,2)).get._2 // another, more typesafe way to get at the private fields

Private constructor

You might think that by making the constructor private, it is possible to enforce invariants. In the example below, you might think that it is impossible to create a range with min > max.

case class Range private (min: Int, max: Int)
object Range {
  def create(a: Int, b: Int): Range =
    if(a < b) new Range(a, b) else new Range(b, a)     
}

But that is not the case:

scala> val wrong = Range.create(2,1).copy(min = 1000)
wrong: Range = Range(1000,2)

You would have to override the copy method as well. By the time you have made this really watertight, you might as well have used a normal class.

like image 108
Rüdiger Klaehn Avatar answered Oct 18 '22 04:10

Rüdiger Klaehn