What is the difference between Scala's case class and class?

I searched in Google to find the differences between a case class and a class . Everyone mentions that when you want to do pattern matching on the class, use case class. Otherwise use classes and also mentioning some extra perks like equals and hash code overriding. But are these the only reasons why one should use a case class instead of class?

I guess there should be some very important reason for this feature in Scala. What is the explanation or is there a resource to learn more about the Scala case classes from?


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.


    Technically, there is no difference between a class and a case class -- even if the compiler does optimize some stuff when using case classes. However, a case class is used to do away with boiler plate for a specific pattern, which is implementing algebraic data types.

    A very simple example of such types are trees. A binary tree, for instance, can be implemented like this:

    sealed abstract class Tree
    case class Node(left: Tree, right: Tree) extends Tree
    case class Leaf[A](value: A) extends Tree
    case object EmptyLeaf extends Tree
    

    That enable us to do the following:

    // DSL-like assignment:
    val treeA = Node(EmptyLeaf, Leaf(5))
    val treeB = Node(Node(Leaf(2), Leaf(3)), Leaf(5))
    
    // On Scala 2.8, modification through cloning:
    val treeC = treeA.copy(left = treeB.left)
    
    // Pretty printing:
    println("Tree A: "+treeA)
    println("Tree B: "+treeB)
    println("Tree C: "+treeC)
    
    // Comparison:
    println("Tree A == Tree B: %s" format (treeA == treeB).toString)
    println("Tree B == Tree C: %s" format (treeB == treeC).toString)
    
    // Pattern matching:
    treeA match {
      case Node(EmptyLeaf, right) => println("Can be reduced to "+right)
      case Node(left, EmptyLeaf) => println("Can be reduced to "+left)
      case _ => println(treeA+" cannot be reduced")
    }
    
    // Pattern matches can be safely done, because the compiler warns about
    // non-exaustive matches:
    def checkTree(t: Tree) = t match {
      case Node(EmptyLeaf, Node(left, right)) =>
      // case Node(EmptyLeaf, Leaf(el)) =>
      case Node(Node(left, right), EmptyLeaf) =>
      case Node(Leaf(el), EmptyLeaf) =>
      case Node(Node(l1, r1), Node(l2, r2)) =>
      case Node(Leaf(e1), Leaf(e2)) =>
      case Node(Node(left, right), Leaf(el)) =>
      case Node(Leaf(el), Node(left, right)) =>
      // case Node(EmptyLeaf, EmptyLeaf) =>
      case Leaf(el) =>
      case EmptyLeaf =>
    }
    

    Note that trees construct and deconstruct (through pattern match) with the same syntax, which is also exactly how they are printed (minus spaces).

    And they can also be used with hash maps or sets, since they have a valid, stable hashCode.


  • Case classes can be pattern matched
  • Case classes automatically define hashcode and equals
  • Case classes automatically define getter methods for the constructor arguments.
  • (You already mentioned all but the last one).

    Those are the only differences to regular classes.

    链接地址: http://www.djcxy.com/p/68264.html

    上一篇: 使用案例类作为Scala中的关键字的高效地图?

    下一篇: 斯卡拉的案例课和课堂课有什么区别?