Técnicamente, no hay diferencia entre una clase y una clase de caso, incluso si el compilador optimiza algunas cosas al usar clases de casos. Sin embargo, una clase de caso se utiliza para eliminar la placa de la caldera para un patrón específico, que está implementando algebraic data types.
Un ejemplo muy simple de tales tipos son los árboles. Un árbol binario, por ejemplo, se puede implementar de esta manera:
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
que nos permiten hacer lo siguiente:
// 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 =>
}
Tenga en cuenta que los árboles construir y deconstruir (a través de coincidencia de patrones) con la misma sintaxis , que también es exactamente cómo se imprimen (menos espacios).
Y también se pueden usar con mapas hash o conjuntos, ya que tienen un hashCode válido y estable.
@Dario Gracias por los punteros. ¿Entonces los ADT son algo así como los Enums? –
@Teja: De alguna manera. Los ADT son enum * enumeraciones parametrizadas *, extremadamente potentes y seguras en cuanto a tipo de letra. – Dario
Las clases de casos sellados se utilizan para imitar los tipos de datos algebraicos. De lo contrario, el número de subclases no está limitado. –