Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do case class companion objects extend FunctionN?

When you create a case class, the compiler creates a corresponding companion object with a few of the case class goodies: an apply factory method matching the primary constructor, equals, hashCode, and copy.

Somewhat oddly, this generated object extends FunctionN.

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

This is only the case if:

  • There is no manually defined companion object
  • There is exactly one parameter list
  • There are no type arguments
  • The case class isn't abstract.

Seems like this was added about two years ago. The latest incarnation is here.

Does anyone use this, or know why it was added? It increases the size of the generated bytecode a little with static forwarder methods, and shows up in the #toString() method of the companion objects:

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

UPDATE

Manually created objects with a single apply method are not automatically considered as FunctionN:

object HasApply {   def apply(a: Int) = 1 } val i = HasApply(1)  // fails //  HasApply: (Int => Int)  
like image 505
retronym Avatar asked Jun 15 '10 21:06

retronym


People also ask

Why do we use companion object?

A companion object is an object that's declared in the same file as a class , and has the same name as the class. A companion object and its class can access each other's private members. A companion object's apply method lets you create new instances of a class without using the new keyword.

Can case class have companion object?

When you want to define some functionality related to a case class you have two possible ways to do this. The first one is to create functions directly in the case class. Note that in order to define a companion object for a class you have to set the same names for them and declare them in the same file.

What is the difference between class and case class in Scala?

A class can extend another class, whereas a case class can not extend another case class (because it would not be possible to correctly implement their equality).

What is the difference between Scala class and object?

Difference Between Scala Classes and Objects Definition: A class is defined with the class keyword while an object is defined using the object keyword. Also, whereas a class can take parameters, an object can't take any parameter. Instantiation: To instantiate a regular class, we use the new keyword.


2 Answers

The reason why case class companion objects implement FunctionN is that before, case classes generated a class and a factory method, not a companion object. When we added extractors to Scala it made more sense to turn the factory method into a full companion object with apply and unapply methods. But then, since the factory method did conform to FunctionN, the companion object needed to conform, too.

[Edit] That said, it would make sense to have companion objects show as their own name, not as "function"

like image 164
Martin Odersky Avatar answered Sep 24 '22 02:09

Martin Odersky


Well, given that target.apply(a1, a2, a3 ... aN) in Scala:

  1. can be sugared by target(a1, a2, a3 ... aN)
  2. is the method which needs to be implemented by FunctionN

it seems natural that a companion object:

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

is really:

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

So the addition seems to be natural to me (I'm not sure why it seems "odd" to you?). As to whether it actually added anything; well, that is for someone smarter than me!

like image 32
oxbow_lakes Avatar answered Sep 23 '22 02:09

oxbow_lakes