J'apprends le scala et j'essaie de suivre le formulaire Scala Cookbook:
trait Animal
trait FurryAnimal extends Animal
case class Dog(name:String) extends Animal
case class Cat(name:String) extends Animal
Maintenant, quand j'ai fait en tant que:
val x = Array(Dog("Fido"),Cat("Felix"))
il montre le résultat comme:
x:Array[Product with Serializable with Animal] = Array(Dog(Fido),Cat(Felix))
Bien que je sache qu'une classe de cas est mélangée à un trait de produit
Ce que je ne comprends pas, c'est: Product with Serializable with Animal
Selon ma compréhension, le produit a quelque chose à voir avec l'appariement de motifs
Je l'ai fait sur Google mais je n'ai rien obtenu.Veuillez m'aider à comprendre le concept en détail.
Merci
Ceci est un comportement attendu en raison du fonctionnement de case class
. case class
automatiquement extends
deux traits, à savoir Product
et Serializable
.
Product
trait est étendu car case class
est un type de données algébrique avec type de produit .
Serializable
trait est étendu de sorte que case class
puisse être traité comme une donnée pure, c'est-à-dire capable d'être sérialisé.
Contrairement à case class
Dog
et Cat
, votre trait Animal
ne s'étend pas Product
ou Serializable
. D'où la signature de type que vous voyez.
Lorsque vous déclarez quelque chose comme Array(Dog(""), Cat(""))
, scalac doit déduire un seul type top pouvant représenter tous les éléments d'un tableau donné.
C'est pourquoi le type inféré est Product with Serializable with Animal
car Animal
n'a pas été étendu Product
ni Serializable
alors que le case class
l'a été implicitement.
Pour contourner cette inférence, vous pouvez rendre le type explicite par Animal
ou rendre Animal
extend Product
et Serializable
.
trait Animal extends Product with Serializable
case class Dog(name: String) extends Animal
case class Cat(name: String) extends Animal
Array(Dog(""), Cat("")) // Array[Animal] = Array(Dog(), Cat())
Toutes les classes de cas à Scala possèdent quelques propriétés:
Product
et une implémentation par défaut leur sera fournie, car ils peuvent être vus comme un produit cartésien de N enregistrements . Serializable
car ils sont sérialisables dès l’origine (en tant que choix de conception). hashCode
et equals
fournie par le compilateur, ce qui facilite la recherche de modèlesapply
et unapply
, pour la composition et la décomposition du type.Les classes de cas sont également la manière dont Scala exprime un type de données algébrique , plus précisément un type de produit . Les n-uplets sont aussi un type de produit }, et ainsi ils étendent également le trait Product
.
Lorsque vous utilisez deux classes de cas avec un trait commun, le compilateur de scala utilisera son algorithme d'inférence de type pour tenter de trouver la meilleure résolution de correspondance pour Array
.
Si vous souhaitez éviter de voir ce détail d'implémentation, vous pouvez demander à votre trait d'étendre explicitement ces traits:
sealed trait Animal extends Product with Serializable
Toutes les classes de cas s'étendent automatiquement Product
et Serializable
. C'est moche? oui . Fondamentalement, Product
peut être considéré comme une collection hétérogène. Toutes les classes de produits à savoir. (Product1, Product2 ...) étend Product
qui contient certaines méthodes courantes à utiliser comme productArity
, productElement
etc.
Comme les classes de cas, les autres types qui développent Product
sont List
, Tuple
etc.
De ma feuille de travail scala,
val product : Product = (10,"String",3) //> product : Product = (10,String,3)
product.productArity //> res0: Int = 3
product.productElement(0) //> res1: Any = 10
product.productElement(1) //> res2: Any = String
product.productElement(2) //> res3: Any = 3
case class ProductCase(age:Int,name:String,ISBN:Int)
ProductCase(23,"som",5465473).productArity //> res4: Int = 3
Pour plus de détails, regardez ici .