38 votes

Pourquoi les objets compagnons de classe de cas étendent-ils FunctionN?

Lorsque vous créez une classe de cas, le compilateur crée un correspondant compagnon objet avec quelques-uns de la classe de cas de goodies: un apply usine méthode correspondant à la primaire constructeur, equals, hashCode, et copy.

Un peu curieusement, cela a généré objet s'étend au-Fonctionn.

scala> case class A(a: Int)                                 
defined class A

scala> A: (Int => A)
res0: (Int) => A = <function1>

C'est seulement le cas si:

  • Il n'est pas défini manuellement compagnon objet
  • Il y a exactement un paramètre de la liste
  • Il n'y a pas des arguments de type
  • Le cas de la classe n'est pas abstraite.

Semble que cela a été ajoutée il y a deux ans. La dernière incarnation est ici.

Personne ne l'utiliser, ou de savoir pourquoi il a été ajouté? Il augmente la taille du bytecode généré un peu statique transitaire méthodes, et dans l' #toString() méthode de la compagne d'objets:

scala> case class A()
defined class A

scala> A.toString
res12: java.lang.String = <function0>

Mise à JOUR

Manuellement les objets créés avec un seul apply méthode ne sont pas automatiquement considérés comme des FunctionN:

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

// fails
//  HasApply: (Int => Int) 

48voto

Martin Odersky Points 13161

La raison pour laquelle la classe de cas de compagnon objets de mettre en œuvre Fonctionn est qu'avant, des classes de cas a généré une classe et une méthode de fabrique, pas un compagnon de l'objet. Lorsque nous avons ajouté extracteurs à Scala, il ne fait plus de sens pour transformer l'usine en pleine compagnon objet à appliquer et délettrer méthodes. Mais ensuite, à partir de la méthode de n'être conformes aux Fonctionn, le compagnon de l'objet nécessaire pour se conformer, trop.

[Edit] cela dit, il serait logique d'avoir pour compagnon les objets de montrer que leur propre nom, et non en tant que "fonction"

11voto

oxbow_lakes Points 70013

Eh bien, étant donné qu' target.apply(a1, a2, a3 ... aN) en Scala:

  1. peut être sucrées en target(a1, a2, a3 ... aN)
  2. est la méthode qui doit être mis en œuvre par FunctionN

il semble naturel qu'un compagnon de l'objet:

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

est vraiment:

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

De sorte que le plus semble être naturel pour moi (je ne suis pas sûr pourquoi, il semble "bizarre" pour vous?). Quant à savoir si elle a effectivement ajouté quoi que ce soit; eh bien, c'est pour quelqu'un de plus malin que moi!

11voto

Miles Sabin Points 13604

Mis à part la réponse d'oxbow_lakes sur le caractère naturel de celui-ci, il peut souvent être utile d'avoir des constructeurs disponibles en tant que fonctions de première classe, en particulier en conjonction avec des fonctions d'ordre supérieur des collections Scala. Pour un exemple (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))
 

5voto

Randall Schulz Points 18820
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!)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X