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

j'ai cherché dans Google pour trouver les différences entre un case class et un class . Tout le monde mentionne que lorsque vous voulez faire l'appariement des motifs dans la classe, utilisez la classe cas. Dans les autres cas, utilisez les classes et mentionnez aussi certains avantages supplémentaires comme les égaux et le code de hachage. Mais est-ce la seule raison pour laquelle on devrait utiliser une classe de cas au lieu de classe?

je suppose qu'il devrait y avoir une raison très importante pour cette caractéristique dans Scala. Qu'est-ce que l' explication ou est-il une ressource pour en savoir plus sur la Scala cas des classes à partir de?

379
demandé sur Freedom_Ben 2010-02-22 20:49:33

14 réponses

Les classes de cas

peuvent être considérées comme des objets simples et immuables contenant des données qui devraient dépendre exclusivement de leurs arguments de constructeur .

ce concept fonctionnel nous permet de

  • utiliser une syntaxe d'initialisation compacte ( Node(1, Leaf(2), None)) )
  • les décomposent en utilisant l'appariement des motifs
  • ont des comparaisons d'égalité implicitement définies

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

si un objet effectue des calculs statiques à l'intérieur ou présente d'autres types de comportement complexe, il doit s'agir d'une classe ordinaire.

335
répondu Dario 2010-02-22 17:57:02

techniquement, il n'y a pas de différence entre une classe et une classe de cas, même si le compilateur optimise certaines choses en utilisant des classes de cas. Cependant, une classe de cas est utilisée pour supprimer la plaque chauffante pour un motif spécifique, qui met en œuvre types de données algébriques .

un exemple très simple de tels types sont les arbres. Un arbre binaire, par exemple, peut être implémenté 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 permettent à nous de faire ce qui suit:

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

noter que les arbres construisent et déconstruisent (par le biais de pattern match) avec la même syntaxe, qui est aussi exactement comment ils sont imprimés (moins les espaces).

et ils peuvent aussi être utilisés avec des cartes ou des ensembles de hachage, car ils ont un hashCode valide et stable.

150
répondu Daniel C. Sobral 2016-10-06 19:51:32
  • les classes de cas peuvent être appariées selon le modèle
  • les classes de cas définissent automatiquement le hashcode et égalent
  • 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 par rapport aux classes régulières.

56
répondu sepp2k 2010-02-22 18:56:32

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

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

où le productArity renvoie le nombre de paramètres de classe, productElement(i) renvoie le i TH paramètre, et productIterator permet itération à travers eux.

24
répondu Jean-Philippe Pellet 2011-01-13 16:41:31

personne n'a mentionné que les classes de cas ont val paramètres constructeur, mais c'est aussi la valeur par défaut pour les classes régulières (qui je pense est une incohérence dans la conception de Scala). Dario a laissé entendre qu'il s'agissait de immuable ".

notez que vous pouvez outrepasser la valeur par défaut en préparant l'argument de chaque constructeur avec var pour les classes de cas. Toutefois, rendre les catégories de cas modifiables fait de leurs méthodes equals et hashCode une variante temporelle.[1]

sepp2k déjà mentionné que les classes de cas génèrent automatiquement les méthodes equals et hashCode .

en outre, personne n'a mentionné que les classes de cas créent automatiquement un compagnon object avec le même nom que la classe, qui contient les méthodes apply et unapply . La méthode apply permet de construire instances sans préparation avec new . La méthode d'extraction unapply permet l'appariement des motifs que d'autres ont mentionné.

le compilateur optimise également la vitesse de match - case correspondance des motifs pour les classes de Cas[2].

[1] Des Classes De Cas Sont Cool

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

23
répondu Shelby Moore III 2013-09-12 08:02:21

la construction de la classe de cas dans Scala peut également être considérée comme une commodité pour enlever une quelconque plaque de chaudronnier.

lors de la construction d'une classe de cas Scala vous donne ce qui suit.

  • Il crée une classe ainsi que son compagnon, l'objet
  • son objet compagnon met en œuvre la méthode apply que vous pouvez utiliser comme une méthode d'usine. Vous obtenez l'avantage de sucre syntaxique de ne pas avoir à utiliser le nouveau mot clé.

parce que la classe est immuable vous obtenez des accesseurs, qui sont juste les variables (ou propriétés) de la classe mais pas de mutateurs (donc pas de capacité à changer les variables). Les paramètres du constructeur sont automatiquement disponibles en tant que champs publics en lecture seule. Beaucoup plus agréable à utiliser que Java bean construire.

  • vous obtenez aussi hashCode , equals , et toString méthodes par défaut et la méthode equals compare la structure d'un objet. Une méthode copy est générée pour pouvoir cloner un objet.

le plus grand avantage comme cela a été mentionné précédemment est le fait que vous pouvez associer des motifs sur les classes de cas. La raison en est que vous obtenez la méthode unapply qui vous permet de déconstruire une classe de cas pour extraire ses champs.


essentiellement ce que vous obtenez de Scala lors de la création d'une classe de cas (ou un objet de cas si votre classe ne prend pas d'arguments) est un objet simple qui sert le but comme une usine et comme un extracteur .

9
répondu Faktor 10 2015-05-29 13:06:39

, Selon Scala documentation :

des classes de Cas sont juste des classes régulières que sont:

  • immuable par défaut
  • Décomposable par le biais de pattern matching
  • comparé par égalité structurelle au lieu de par référence
  • Succinct d'instancier et d'exploiter sur

une autre caractéristique du mot-clé case est que le compilateur génère automatiquement plusieurs méthodes pour nous, y compris les méthodes familières toString, equals, et hashCode en Java.

4
répondu Amine Sagaama 2017-03-28 00:13:08

Classe:

scala> class Animal(name:String)
defined class Animal

scala> val an1 = new Animal("Padddington")
an1: Animal = Animal@748860cc

scala> an1.name
<console>:14: error: value name is not a member of Animal
       an1.name
           ^

mais si nous utilisons le même code mais utiliser la classe de cas:

scala> case class Animal(name:String)
defined class Animal

scala> val an2 = new Animal("Paddington")
an2: Animal = Animal(Paddington)

scala> an2.name
res12: String = Paddington


scala> an2 == Animal("fred")
res14: Boolean = false

scala> an2 == Animal("Paddington")
res15: Boolean = true

catégorie de personnes:

scala> case class Person(first:String,last:String,age:Int)
defined class Person

scala> val harry = new Person("Harry","Potter",30)
harry: Person = Person(Harry,Potter,30)

scala> harry
res16: Person = Person(Harry,Potter,30)
scala> harry.first = "Saily"
<console>:14: error: reassignment to val
       harry.first = "Saily"
                   ^
scala>val saily =  harry.copy(first="Saily")
res17: Person = Person(Saily,Potter,30)

scala> harry.copy(age = harry.age+1)
res18: Person = Person(Harry,Potter,31)

Pattern Matching:

scala> harry match {
     | case Person("Harry",_,age) => println(age)
     | case _ => println("no match")
     | }
30

scala> res17 match {
     | case Person("Harry",_,age) => println(age)
     | case _ => println("no match")
     | }
no match

objet: singleton:

scala> case class Person(first :String,last:String,age:Int)
defined class Person

scala> object Fred extends Person("Fred","Jones",22)
defined object Fred
3
répondu user1668782 2016-09-16 12:42:22

personne n'a mentionné que l'objet compagnon de classe de cas a tupled defention, qui a un type:

case class Person(name: String, age: Int)
//Person.tupled is def tupled: ((String, Int)) => Person

le seul cas d'utilisation que je peux trouver est quand vous avez besoin de construire la classe de cas de tuple, exemple:

val bobAsTuple = ("bob", 14)
val bob = (Person.apply _).tupled(bobAsTuple) //bob: Person = Person(bob,14)

vous pouvez faire la même chose, sans tupled, en créant l'objet directement, mais si vos ensembles de données exprimés en liste de tuple avec arity 20(tuple avec 20 éléments), peut être en utilisant tupled est votre choix.

2
répondu Slow Harry 2017-01-11 15:18:22

Un classe de cas de est une classe qui peut être utilisé avec le match/case .

def isIdentityFun(term: Term): Boolean = term match {
  case Fun(x, Var(y)) if x == y => true
  case _ => false
}

vous voyez que case est suivi d'une instance de classe Fun dont le 2e paramètre est un Var. C'est une syntaxe très agréable et puissante, mais elle ne peut pas fonctionner avec les instances d'une classe, donc il y a des restrictions pour les classes de cas. Et si ces restrictions sont respectées, il est possible de définir automatiquement hashcode et equals.

l'expression vague" un mécanisme récursif de décomposition par appariement de motifs "signifie simplement "cela fonctionne avec case ". (En effet, L'instance suivie par match est comparée à (comparée à) l'instance qui suit case , Scala doit les décomposer tous les deux, et doit décomposer récursivement de quoi ils sont faits.)

à quoi servent les classes de cas ? L'article Wikipédia sur L'algébrique Les types de données donnent deux bons exemples classiques, des listes et des arbres. La prise en charge des types de données algébriques (y compris savoir les comparer) est un must pour tout langage fonctionnel moderne.

quelles classes de cas sont et non utiles pour? Certains objets ont l'état, le code comme connection.setConnectTimeout(connectTimeout) n'est pas pour les classes de cas.

et maintenant vous pouvez lire un Tour de Scala: cas Classes

2
répondu 18446744073709551615 2017-03-15 12:15:46

outre ce que les gens ont déjà dit, il y a quelques différences plus fondamentales entre class et case class

1. Case Class n'a pas besoin de new explicite, alors que la classe doit être appelée avec new

val classInst = new MyClass(...)  // For classes
val classInst = MyClass(..)       // For case class

2.By les paramètres par défaut des constructeurs sont privés dans class , tandis que son public dans case class

// For class
class MyClass(x:Int) { }
val classInst = new MyClass(10)

classInst.x   // FAILURE : can't access

// For caseClass
case class MyClass(x:Int) { }
val classInst = MyClass(10)

classInst.x   // SUCCESS

3. case class se comparent par valeur 1519120920"

// case Class
class MyClass(x:Int) { }

val classInst = new MyClass(10)
val classInst2 = new MyClass(10)

classInst == classInst2 // FALSE

// For Case Class
case class MyClass(x:Int) { }

val classInst = MyClass(10)
val classInst2 = MyClass(10)

classInst == classInst2 // TRUE
2
répondu DeepakKg 2017-11-02 09:44:34

Contrairement aux classes, les classes de cas ne sont utilisées que pour contenir des données.

les classes de cas sont flexibles pour les applications centrées sur les données, ce qui signifie que vous pouvez définir les champs de données dans la classe de cas et définir la logique commerciale dans un objet compagnon. De cette façon, vous séparez les données de la logique commerciale.

avec la méthode de Copie, vous pouvez hériter n'importe quelle ou toutes les propriétés requises de la source et pouvez les changer comme vous voulez.

1
répondu Reddeiah Pidugu 2017-09-20 19:05:14
  • classes de définir un compagnon de l'objet à appliquer et à annuler les méthodes
  • des classes de Cas extends Serializable
  • classes de cas define égale hashCode et méthodes de copie
  • Tous les attributs de l'constructeur val (sucre syntaxique)
0
répondu tictactoki 2017-04-26 16:03:35

je pense que dans l'ensemble, toutes les réponses ont donné une explication sémantique au sujet des classes et des classes de cas. Cela pourrait être très pertinent, mais chaque internaute novice à scala devrait savoir ce qui se passe quand vous créez une classe de cas. J'ai écrit cette réponse , qui explique la classe de cas en un mot.

chaque programmeur devrait savoir que s'ils utilisent des fonctions pré-construites, alors ils écrivent un code comparativement moins, ce qui leur permet en donnant le pouvoir d'écrire le code le plus optimisé, mais le pouvoir vient avec de grandes responsabilités. Ainsi, utilisez des fonctions prébuilt avec des précautions très.

certains développeurs évitent d'écrire des classes de cas en raison de 20 méthodes supplémentaires, que vous pouvez voir en démontant le fichier de classe.

s'il vous Plaît consultez ce lien si vous voulez vérifier toutes les méthodes à l'intérieur d'une classe de cas de .

0
répondu arglee 2018-06-13 19:33:30