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:
- puede ser azucarado por el
target(a1, a2, a3 ... aN)
- 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!)