493 votes

Quelle est la différence entre la classe de cas et la classe de Scala?

J'ai cherché dans Google pour trouver les différences entre les cas de classe et une classe. Tout le monde mentionne que lorsque vous voulez faire un patron sur la classe, le cas d'utilisation en classe. Sinon, l'utilisation de classes et également de mentionner certains avantages supplémentaires comme des égaux et hascode primordial. Mais sont-ce là les seules raisons pour lesquelles on devrait utiliser une classe de cas de la place de la classe?

Je suppose qu'il doit y avoir une raison très forte pour cette fonction en Scala. Quelle est l'explication ou est-il une ressource pour en savoir plus sur la Scala cas des classes à partir de?

448voto

Dario Points 26259

Des classes de cas peut être considéré comme de la plaine et des données immuables de rétention d'objets qui devraient dépendre exclusivement de leurs arguments du constructeur.

Cette notion fonctionnelle nous permet de

  • l'utilisation d'un compact initialisation de la syntaxe (Node(1, Leaf(2), None)))
  • de les décomposer en utilisant l'appariement
  • l'égalité des comparaisons implicitement défini

En combinaison avec l'héritage, les classes de cas sont utilisées pour imiter algébrique de types de données.

Si un objet effectue dynamique des calculs sur l'intérieur ou de l'exposition à d'autres types de comportement complexe, il devrait être une classe ordinaire.

175voto

Daniel C. Sobral Points 159554

Techniquement, il n'y a pas de différence entre une classe et une classe de cas, même si le compilateur ne optimiser certaines choses lors de l'utilisation de classes de cas. Cependant, un cas de classe est utilisé pour faire disparaître la plaque de la chaudière pour un modèle spécifique, qui est la mise en œuvre des types de données algébriques.

Un exemple très simple de ces types sont des arbres. Un arbre binaire, par exemple, peut être mis en œuvre comme ceci:

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

Qui nous permettent d'effectuer les opérations suivantes:

// 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 =>
}

Notez que les arbres à construire et à déconstruire (par motif) avec la même syntaxe, qui est aussi exactement comment ils sont imprimées (sans les espaces).

Et ils peuvent également être utilisés avec pommes de cartes ou de jeux, car ils ont un valide, stable hashCode.

79voto

sepp2k Points 157757
  • Les classes de cas peuvent être appariées
  • Les classes de cas définissent automatiquement le hashcode et sont égales
  • Les classes de cas définissent automatiquement les méthodes getter pour les arguments du constructeur.

(Vous avez déjà mentionné tout sauf le dernier).

Ce sont les seules différences avec les classes régulières.

32voto

Shelby Moore III Points 2088

Personne n'a indiqué que des classes de cas ont val paramètres du constructeur et pourtant, c'est aussi la valeur par défaut pour les classes régulières (ce qui je pense est une incohérence dans la conception de la Scala). Dario implicite, par exemple, où il a indiqué qu'ils sont "immuable".

Remarque-vous pouvez remplacer la valeur par défaut en ajoutant la chaque argument du constructeur avec var pour les classes de cas. Toutefois, avant de faire des classes de cas mutable causes de leur equals et hashCode méthodes à temps variant.[1]

sepp2k déjà mentionné le cas des classes de générer automatiquement equals et hashCode méthodes.

Aussi personne n'a indiqué que les classes de créer automatiquement un compagnon object avec le même nom que la classe, qui contient apply et unapply méthodes. L' apply méthode permet de construire des cas, sans les préfixant avec new. L' unapply extracteur méthode permet la correspondance de modèle que d'autres l'ont mentionné.

Aussi le compilateur optimise la vitesse de l' match-case correspondant à un modèle pour les classes de cas[2].

[1] Des Classes De Cas Sont Cool

[2] le Cas des Classes et des Extracteurs, page 15.

30voto

Jean-Philippe Pellet Points 25240

Personne n'a mentionné que les classes de cas sont aussi des instances de Product et donc héritent de ces méthodes:

 def productElement(n: Int): Any
def productArity: Int
def productIterator: Iterator[Any]
 

productArity renvoie le nombre de paramètres de classe, productElement(i) renvoie le i ième paramètre et productIterator permet d 'itérer à travers eux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X