tags:

views:

216

answers:

4

Case classes in Scala are standard classes enhanced with pattern-matching, equals, ... (or am I wrong?). Moreover they require no "new" keyword for their instanciation. It seems to me that they are simpler to define than regular classes (or am I again wrong?).

There are lots of web pages telling where they should be used (mostly about pattern matchin). But where should they be avoided ? Why don't we use them everywhere ?

+10  A: 

Inheriting from case classes is problematic. Suppose you have code like so:

case class Person(name: String) { }

case class Homeowner(address: String,override val name: String)
  extends Person(name) { }

scala> Person("John") == Homeowner("1 Main St","John")
res0:  Boolean = true

scala> Homeowner("1 Main St","John") == Person("John")
res1: Boolean = false

Perhaps this is what you want, but usually you want a==b if and only if b==a. Unfortunately, the compiler can't sensibly fix this for you automatically.

This gets even worse because the hashCode of Person("John") is not the same as the hashCode of Homeowner("1 Main St","John"), so now equals acts weird and hashCode acts weird.

As long as you know what to expect, inheriting from case classes can give comprehensible results, but it has come to be viewed as bad form (and thus has been deprecated in 2.8).

Rex Kerr
Do you have a link to the deprecated feature that you mention, please?
saucisson
Search "case class inheritance deprecated" on Google and the top three hits will discuss it. The deprecation is in the 2.8 codebase already--if you download a nightly build you can try it out with a trivial example.
Rex Kerr
+10  A: 

There are many places where case classes are not adequate:

  • When one wishes to hide the data structure.
  • As part of a type hierarchy of more than two or three levels.
  • When the constructor requires special considerations.
  • When the extractor requires special considerations.
  • When equality and hash code requires special considerations.

Sometimes these requirements show up late in the design, and requires one to convert a case class into a normal class. Since the benefits of a case class really aren't all that great -- aside from the few special cases they were specially made for -- my own recommendation is not to make anything a case class unless there's a clear use for it.

Or, in other words, do not overdesign.

Daniel
A: 

It can be tempting to use case classes because you want free toString/equals/hashCode. This can cause problems, so avoid doing that.

I do wish there were an annotation that let you get those handy things without making a case class, but maybe that's harder than it sounds.

kikibobo
"can cause problems". what problems?
Seth Tisue
A: 

One downside that is mentioned in Programming in Scala is that due to the things automatically generated for case classes the objects get larger than for normal classes, so if memory efficiency is important, you might want to use regular classes.

Fabian Steeg