type parameter implicitly generic for comprehension scala case-class companion-object

implicitly - type parameter scala



¿Por qué los objetos complementarios de la clase de caso extienden la función N? (4)

Aparte de la respuesta de oxbow_lakes acerca de la naturalidad de la misma, a menudo puede ser útil tener constructores disponibles como funciones de primera clase, particularmente en conjunto con las funciones de orden superior de las colecciones Scala. Para un ejemplo (trivial),

scala> case class Foo(i : Int) defined class Foo scala> List(1, 2, 3) map Foo res0: List[Foo] = List(Foo(1), Foo(2), Foo(3))

Cuando se crea una clase de caso, el compilador crea un objeto complementario correspondiente con algunas de las hashCode de la clase de caso: un método de fábrica de apply que coincida con el constructor primario, equals , hashCode y copy .

Curiosamente, este objeto generado se extiende a FunctionN.

scala> case class A(a: Int) defined class A scala> A: (Int => A) res0: (Int) => A = <function1>

Este es solo el caso si:

  • No hay un objeto complementario definido manualmente
  • Hay exactamente una lista de parámetros
  • No hay argumentos de tipo
  • La clase de caso no es abstracta.

Parece que esto fue added hace dos años. La última encarnación está here .

¿Alguien usa esto o sabe por qué fue agregado? Aumenta un poco el tamaño del bytecode generado con los métodos de promotor estático, y se muestra en el método #toString() de los objetos complementarios:

scala> case class A() defined class A scala> A.toString res12: java.lang.String = <function0>

ACTUALIZAR

Los objetos creados manualmente con un solo método de apply no se consideran automáticamente como FunctionN :

object HasApply { def apply(a: Int) = 1 } val i = HasApply(1) // fails // HasApply: (Int => Int)


Bueno, dado ese target.apply(a1, a2, a3 ... aN) en Scala:

  1. puede ser azucarado por el target(a1, a2, a3 ... aN)
  2. es el método que necesita ser implementado por FunctionN

parece natural que un objeto compañero:

object MyClass { def apply(a1 : A1, ... aN: AN) = new MyClass(a1, ..., aN) }

realmente es:

object MyClass extends FunctionN[A1, ... , AN, MyClass]{ def apply(a1 : A1, ... aN: AN) = new MyClass(a1, ..., aN) }

Entonces la adición parece ser natural para mí (no estoy seguro de por qué te parece "extraño"). En cuanto a si realmente agregó algo; ¡Bueno, eso es para alguien más inteligente que yo!


La razón por la que los objetos complementarios de la clase de caso implementan la función N es que antes, las clases de caso generaban una clase y un método de fábrica, no un objeto complementario. Cuando agregamos extractores a Scala, tenía más sentido convertir el método de fábrica en un objeto complementario completo con los métodos de aplicar y quitar la aplicación. Pero luego, dado que el método de fábrica se ajustaba a la función N, el objeto complementario también tenía que ajustarse.

[Editar] Dicho esto, tendría sentido que los objetos acompañantes se muestren como su propio nombre, no como "función"


Welcome to Scala version 2.8.0.RC3 (Java HotSpot(TM) Client VM, Java 1.6.0_20). scala> case class CC3(i: Int, b: Boolean, s: String) defined class CC3 scala> CC3 res0: CC3.type = <function3> scala> CC3.apply(1, true, "boo!") res1: CC3 = CC3(1,true,boo!) scala> CC3(1, true, "boo!") res2: CC3 = CC3(1,true,boo!)