Les classes de cas Scala ont une limite de 22 champs dans le constructeur. Je veux dépasser cette limite, existe-t-il un moyen de le faire avec l'héritage ou la composition qui fonctionne avec les classes de cas?
Plus récemment (octobre 2016, six ans après l'OP), le blog " Scala et 22 " de Richard Dallaway explore cette limite:
En 2014, lorsque Scala 2.11 a été publié, une limitation importante a été supprimée:
Case classes with > 22 parameters are now allowed.
Cela dit, il existe toujours une limite sur le nombre de champs de classe de cas, veuillez consulter https://stackoverflow.com/a/55498135/1586965
Cela peut vous faire penser qu'il n'y a pas 22 limites dans Scala, mais ce n'est pas le cas. La limite persiste dans les fonctions et les tuples .
Le correctif ( PR 2305 ) introduit dans Scala 2.11 a supprimé la limitation pour les scénarios courants ci-dessus: construction de classes de cas, accès aux champs (y compris la copie) et correspondance de modèles ( découvrant les cas Edge ).
Il l'a fait en omettant
unapply
ettupled
pour les classes de cas au-dessus de 22 champs.
En d'autres termes, la limite àFunction22
etTuple22
existe toujours.Contourner la limite (post Scala 2.11)
Il existe deux astuces courantes pour contourner cette limite.
La première consiste à utiliser des tuples imbriqués .
Bien qu'il soit vrai qu'un Tuple ne peut pas contenir plus de 22 éléments, chaque élément lui-même pourrait être un TupleL'autre astuce courante consiste à utiliser des listes hétérogènes (HLists), où il n'y a pas de limite 22.
Si vous souhaitez utiliser des classes de cas, il est préférable d'utiliser l'implémentation HList sans forme. Nous avons créé la bibliothèque Slickless pour vous faciliter la tâche. En particulier la récente méthode
mappedWith
convertit entre les classesHLists
sans forme et les classes de cas. Cela ressemble à ceci:
import slick.driver.H2Driver.api._
import shapeless._
import slickless._
class LargeTable(tag: Tag) extends Table[Large](tag, "large") {
def a = column[Int]("a")
def b = column[Int]("b")
def c = column[Int]("c")
/* etc */
def u = column[Int]("u")
def v = column[Int]("v")
def w = column[Int]("w")
def * = (a :: b :: c :: /* etc */ :: u :: v :: w :: HNil)
.mappedWith(Generic[Large])
}
Il y a exemple complet avec 26 colonnes dans la base de code Slickless.
Ce problème va être corrigé dans Scala 2.11.
Construisez une classe normale qui agit comme une classe de cas.
J'utilise toujours scala 2.10.X car c'est la dernière version prise en charge par Spark, et dans Spark-SQL, j'utilise beaucoup les classes de cas.
La solution de contournement pour case classes
avec plus de 22 champs:
class Demo(val field1: String,
val field2: Int,
// .. and so on ..
val field23: String)
extends Product
//For Spark it has to be Serializable
with Serializable {
def canEqual(that: Any) = that.isInstanceOf[Demo]
def productArity = 23 // number of columns
def productElement(idx: Int) = idx match {
case 0 => field1
case 1 => field2
// .. and so on ..
case 22 => field23
}
}
Il est intéressant que votre constructeur soit chargé, mais vous pouvez empaqueter les valeurs associées dans une classe de cas qui leur est propre.
Donc, alors que vous pourriez avoir
case class MyClass(street: String, city: String, state: String, Zip: Integer)
tu peux le faire
case class MyClass(address: Address)
Vous avez également d'autres options:
Function23
trait (ou autre)MISE À JOUR: Comme d'autres l'ont remarqué, ce n'est plus un problème après la sortie de Scala 2.11 - bien que j'hésiterais à utiliser le terme "correctif". Cependant, le "Catch 22", si vous le souhaitez, apparaît parfois dans des bibliothèques tierces Scala.