为什么case类伴侣对象扩展FunctionN?

当你创build一个case类时,编译器会创build一个相应的伴随对象,其中包含一些case类的好东西:一个apply工厂方法匹配主构造函数equalshashCodecopy

有点奇怪,这个生成的对象扩展了FunctionN。

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

只有在以下情况下才能这样做:

  • 没有手动定义的伴侣对象
  • 只有一个参数列表
  • 没有types参数
  • 案例类不是抽象的。

似乎是两年前添加的 。 最新的化身在这里 。

有没有人使用这个,或知道为什么被添加? 它使用静态转发器方法稍微增加了生成的字节码的大小,并显示在伴随对象的#toString()方法中:

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

UPDATE

使用单个apply方法手动创build的对象不会被自动视为FunctionN

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

case类伴侣对象实现FunctionN的原因是,case类之前生成一个类和一个工厂方法,而不是伴随对象。 当我们将提取器添加到Scala中时,使用apply和unapply方法将工厂方法转换为完整的伴随对象更有意义。 但是,由于工厂方法确实符合FunctionN,伴侣对象也需要符合。

也就是说,将伴侣对象显示为自己的名字是有意义的,而不是“function”

那么,在Scala中给出target.apply(a1, a2, a3 ... aN)

  1. 可以被target(a1, a2, a3 ... aN)加糖target(a1, a2, a3 ... aN)
  2. FunctionN需要实现的方法

同伴对象似乎是自然的:

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

是真的:

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

所以这个增加对我来说似乎是很自然的(我不确定你为什么觉得“奇怪”)? 至于是否真的加了什么东西, 好吧,那是比我聪明的人!

除了oxbow_lakes关于它的自然性的回答之外,把构造函数作为一stream函数可用通常是有用的,特别是与Scala集合的高阶函数相结合。 对于(一个微不足道的)例子,

 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)) 
 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!)