11

I have problems understanding correctly the use of class and their companion object.

When defining a case class there is its companion object that comes with it, but what is the result of defining an object having the same name as the case class? Does it override the companion object? And how to access case class parameters?

For example in TestCaseClass.scala file I define the following :

case class TestCaseClass(att1: String, att2: Int, att4s: List[String])

object TestCaseClass {

  def iWantDoSomethingWithMyParams: String = {
    att1 + " " + att2
  }

  // Other functions
}

object AnotherTestCaseClass {

  def iWantDoSomethingWithTestCaseClassParams: String = {
  // How to access TestCaseClass.att1
    TestCaseClass.att1 + " " + TestCaseClass.att2
  }

  def iWantGetAllAttr4: List[String] = {
     // ???
  }
}
jerome
  • 2,029
  • 4
  • 38
  • 58

2 Answers2

20

To some extent, giving an object the same name as a class (or trait) is just a matter of convention. But it also has a bit of special meaning.

The companion object is a singleton class just like any other object. If you want a method in the companion object to interact with an instance of the class, you have to pass it an instance of the class just like in any other situation. So, to fix your first example:

case class TestCaseClass(att1: String, att2: Int, att4s: List[String])

object TestCaseClass {    
  def iWantDoSomethingWithMyParams(x: TestCaseClass): String =
    x.att1 + " " + x.att2
}

The class and the object do not "override" or step on each other's toes in any way because classes and objects belong to different namespaces. Class names are used at the type level (and also in constructor calls), and object names are used at the term level.

There are a few relationships between a class and its companion:

  • It does affect how implicits are resolved - Any implicts defined in a class's companion object are automatically brought into scope.

  • private members of the class are visible to the object, and vice versa.

  • Case classes are a little bit different, because case class is actually a shorthand which, in addition to defining a class, also adds apply and unapply methods to its companion object.

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
  • 1
    If it does not have any meaning to name the companion object as the class - what makes it a companion object? The fact that it is defined in the same file? – Make42 Oct 16 '17 at 11:50
  • 1
    @ChrisMartin: Yes, I read the entire post :-). I did not want to discuss what the companion object is or does, but am interested in how to designate that an object "Y" (singleton, not "regular class instance") is a companion object for regular class "X". For example: "The compiler knows that Y is the companion object of class X, because X and Y are defined in the same file." or maybe it is "The compiler knows that Y is the companion of X because they both have the same name." What is it - or is it something totally different? – Make42 Oct 17 '17 at 08:20
  • I thought it was the later, but you wrote "Giving an object the same name as a class (or trait) does not have much special meaning. It is mostly a matter of convention." which disagrees with what I thought. I was referring to that statement of yours when I wrote "any meaning to name the companion object as the class". – Make42 Oct 17 '17 at 08:22
  • Ah. I believe the compiler determines the companion relationship by whether they have the same *fully-qualified* name. (Which, yes, as far as I know, means they have to be in the same file.) – Chris Martin Oct 17 '17 at 18:04
  • 2
    @ChrisMartin "I believe the compiler determines the companion relationship by whether they have the same fully-qualified name" => This implies that the object class should have the same name as the case class to be considered a companion object. Shouldn't the answer be updated? -> "Giving an object the same name as a class (or trait) does not have much special meaning. It is mostly a matter of convention." (Unless I understand something incorrectly.) – ksceriath Apr 10 '19 at 08:30
  • @ksceriath I suppose "much" was as a weasel word in that sentence. I've rephrased. – Chris Martin Apr 10 '19 at 18:31
1

I would kindly like to add one piece of information to the accepted answer that wasn't clear to me after reading it a couple of times; it's from the Scala Book (all credits to mlachkar, 0x54321 and alvinj):

A companion object in Scala is an object that’s declared in the same file as a class, and has the same name as the class. For instance, when the following code is saved in a file named Pizza.scala, the Pizza object is considered to be a companion object to the Pizza class:

class Pizza {
}

object Pizza {
}
Ricardo
  • 3,696
  • 5
  • 36
  • 50