创建案例类时,编译器会创建一个对应的伴随对象,其中包含一些案例类的好处:与主构造函数 equals
, hashCode
和 copy
匹配的 apply
工厂方法 .
奇怪的是,这个生成的对象扩展了FunctionN .
scala> case class A(a: Int)
defined class A
scala> A: (Int => A)
res0: (Int) => A = <function1>
只有在以下情况下才会这样:
-
没有手动定义的伴随对象
-
只有一个参数列表
-
没有类型参数
-
案例类不是抽象的 .
大约两年前,这似乎是added . 最新的化身是here .
有没有人使用它,或者知道它为什么被添加?它使用静态转发器方法稍微增加了生成的字节码的大小,并显示在随播对象的 #toString()
方法中:
scala> case class A()
defined class A
scala> A.toString
res12: java.lang.String = <function0>
UPDATE
使用单个 apply
方法手动创建的对象不会自动视为 FunctionN
:
object HasApply {
def apply(a: Int) = 1
}
val i = HasApply(1)
// fails
// HasApply: (Int => Int)
4 回答
好吧,鉴于Scala中的
target.apply(a1, a2, a3 ... aN)
:可以被
target(a1, a2, a3 ... aN)
加糖是需要由
FunctionN
实现的方法一个伴侣对象似乎很自然:
是真的:
所以添加对我来说似乎很自然(我不确定为什么它似乎在你身上?) . 至于它是否真的添加了任何东西;好吧,那是为了比我聪明的人!
除了oxbow_lakes关于它的自然性的回复之外,将构造函数作为第一类函数提供通常是有用的,特别是与Scala集合的高阶函数结合使用 . 对于(一个微不足道的)例子,
case类伴随对象实现FunctionN的原因是之前,case类生成了一个类和一个工厂方法,而不是一个伴随对象 . 当我们向Scala添加提取器时,使用apply和unapply方法将工厂方法转换为完整的伴随对象更有意义 . 但是,由于工厂方法确实符合FunctionN,因此伴随对象也需要符合 .
[编辑]那就是说,让伴侣对象显示为自己的名字,而不是“功能”是有意义的