Почему случай классифицирует сопутствующие объекты, расширяют FunctionN?

При создании класса случая компилятор создает соответствующий сопутствующий объект с несколькими положительных героев класса случая: 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) 

38
задан rjsvaljean 20 October 2012 в 15:32
поделиться

4 ответа

Причина, по которой сопутствующие объекты класса case реализуют FunctionN, заключается в том, что раньше классы case генерировали класс и фабричный метод, а не сопутствующий объект. Когда мы добавили экстракторы в Scala, имело больше смысла превратить фабричный метод в полноценный сопутствующий объект с методами apply и unapply. Но затем, поскольку фабричный метод действительно соответствовал FunctionN, сопутствующий объект также должен был соответствовать.

[Edit] Тем не менее, было бы разумно, чтобы сопутствующие объекты отображались как их собственное имя, а не как «функция»

48
ответ дан 27 November 2019 в 03:30
поделиться

Помимо ответа 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))
11
ответ дан 27 November 2019 в 03:30
поделиться

Что ж, учитывая, что target.apply (a1, a2, a3 ... aN) в Scala:

  1. может быть засахарен 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)
}

Таким образом, кажется, что добавление быть естественным для меня (я не уверен, почему это кажется вам "странным"?). Что касается того, действительно ли он добавил что-нибудь ; ну это для кого умнее меня!

11
ответ дан 27 November 2019 в 03:30
поделиться
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!)
5
ответ дан 27 November 2019 в 03:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: