Технически, нет разницы между классом и классом case, даже если компилятор оптимизирует некоторые вещи при использовании классов классов. Однако класс случая используется для устранения плиты котла для определенного рисунка, который реализует algebraic data types.
Очень простой пример таких типов - это деревья. Бинарное дерево, например, может быть реализована следующим образом:
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
Это позволит нам сделать следующее:
// 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 =>
}
Обратите внимание, что деревья строительства и деконструкции (через сопоставление с образцом) с тем же синтаксисом , что также точно так, как они печатаются (минус пробелы).
И они также могут использоваться с картами или наборами хэшей, так как они имеют действительный стабильный хэш-код.
@Dario Спасибо за указателями. Итак, ADT - это что-то вроде Enums? –
@Teja: В некотором роде. ADT являются параметрами enum *, чрезвычайно мощными и типичными. – Dario
Классы закрытых классов используются для имитации алгебраических типов данных. В противном случае количество подклассов не ограничено. –