При создании класса случая компилятор создает соответствующий сопутствующий объект с несколькими положительных героев класса случая: apply
метод фабрики, соответствующий основному конструктору, equals
, hashCode
, и copy
.
Несколько странно этот сгенерированный объект расширяет FunctionN.
scala> case class A(a: Int)
defined class A
scala> A: (Int => A)
res0: (Int) => A =
Это только имеет место если:
Кажется, что это было добавлено приблизительно два года назад. Последнее воплощение здесь.
Кто-либо использует это или знает, почему это было добавлено? Это увеличивает размер сгенерированного байт-кода немного со статическими методами средства передачи и обнаруживается в #toString()
метод сопутствующих объектов:
scala> case class A()
defined class A
scala> A.toString
res12: java.lang.String =
ОБНОВЛЕНИЕ
Вручную созданные объекты с синглом apply
метод автоматически не рассматривают как FunctionN
:
object HasApply {
def apply(a: Int) = 1
}
val i = HasApply(1)
// fails
// HasApply: (Int => Int)
Причина, по которой сопутствующие объекты класса case реализуют FunctionN, заключается в том, что раньше классы case генерировали класс и фабричный метод, а не сопутствующий объект. Когда мы добавили экстракторы в Scala, имело больше смысла превратить фабричный метод в полноценный сопутствующий объект с методами apply и unapply. Но затем, поскольку фабричный метод действительно соответствовал FunctionN, сопутствующий объект также должен был соответствовать.
[Edit] Тем не менее, было бы разумно, чтобы сопутствующие объекты отображались как их собственное имя, а не как «функция»
Помимо ответа oxbow_lakes о его естественности, часто бывает полезно иметь конструкторы, доступные как функции первого класса, особенно в сочетании с функциями высшего порядка коллекций 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))
Что ж, учитывая, что target.apply (a1, a2, a3 ... aN)
в Scala:
target (a1 , a2, a3 ... aN)
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)
}
Таким образом, кажется, что добавление быть естественным для меня (я не уверен, почему это кажется вам "странным"?). Что касается того, действительно ли он добавил что-нибудь ; ну это для кого умнее меня!
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!)