¿Cómo sortear el límite de la clase de caso de Scala de 22 campos?

Las clases de casos de Scala tienen un límite de 22 campos en el constructor. Quiero superar este límite, ¿hay alguna forma de hacerlo con la herencia o la composición que funcione con las clases de casos?

Más recientemente (octubre de 2016, seis años después del OP), la entrada del blog ” Scala y 22 ” de Richard Dallaway explora ese límite:

En 2014, cuando se lanzó Scala 2.11, se eliminó una limitación importante:

Case classes with > 22 parameters are now allowed. 

Esto puede llevarlo a pensar que no hay 22 límites en Scala, pero ese no es el caso. El límite pervive en funciones y tuplas .

El arreglo ( PR 2305 ) introducido en Scala 2.11 eliminó la limitación para los escenarios comunes anteriores: construcción de clases de casos, acceso de campo (incluido el copiado) y coincidencia de patrones ( casos de exclusión de límites ).

Hizo esto al omitir la unapply y el tupled para las clases de casos por encima de 22 campos.
En otras palabras, el límite para Function22 y Tuple22 aún existe.

Trabajando alrededor del límite (post Scala 2.11)

Hay dos trucos comunes para superar este límite.

  • El primero es usar tuplas anidadas .
    Aunque es cierto que una tupla no puede contener más de 22 elementos, cada elemento en sí podría ser una tupla

  • El otro truco común es usar listas heterogéneas (HLists), donde no hay un límite de 22.

Si desea utilizar las clases de casos, puede ser mejor utilizar la implementación HList informe. Creamos la biblioteca de Slickless para que sea más fácil. En particular, el método mappedWith reciente convierte entre HLists sin HLists y clases de casos. Se parece a esto:

 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]) } 

Hay un ejemplo completo con 26 columnas en la base de código Slickless.

Este problema se solucionará en Scala 2.11.

Construye una clase normal que actúe como una clase de caso.

Todavía uso Scala 2.10.X ya que es lo último compatible con Spark, y en Spark-SQL utilizo mucho las clases de casos.

La solución alternativa para las case classes con más de 22 campos:

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

Es interesante que tu constructor esté cargado, pero podrías empaquetar los valores relacionados en una clase case propia.

Entonces, si bien podrías tener

 case class MyClass(street: String, city: String, state: String, zip: Integer) 

Puedes hacerlo

 case class MyClass(address: Address) 

Usted tiene otras opciones también:

  • Agrupe los artículos en tuplas
  • Crea tu propio rasgo de Function23 (o lo que sea)
  • Use currying

ACTUALIZACIÓN: Como otros han notado, esto ya no es un problema después del lanzamiento de Scala 2.11, aunque dudaría en usar el término “corregir”. Sin embargo, el “Catch 22”, si lo desea, a veces aún aparece en las bibliotecas de Scala de terceros.

Cuando tiene tantos valores, generalmente es una señal de que su diseño debe ser revisado de todos modos.

Forme clases de caso intermitentes que luego se agreguen al más grande. Esto también hace que el código sea mucho más fácil de entender, razonar y mantener. Además de eludir este problema que está teniendo.

Por ejemplo, si quisiera almacenar datos de usuario, podría hacer esto …

 case class User(name: Name, email: String) case class Name(first: String, last: String) 

Con tan pocas cosas, esto por supuesto no sería necesario. Pero si tiene 22 cosas que está tratando de agrupar en una sola clase, querrá hacer este tipo de trabajo de clase de caso intermitente de todos modos.