Companion class requires import of Companion object methods and nested objects?
Asked Answered
T

1

14

I am looking at Akka related typesafe activator code and the following construct intrigued me:

Companion object:

object MarkerActor {
  sealed trait MarkerMessage
  case object Stop extends MarkerMessage
   ..
  def objectMethod = print("hi from companion object")
}

Companion class: it imports the companion object methods:

class MarkerActor extends Actor with ActorLogging {
    import MarkerActor._   // Comment this line to compare w or w/o import available

    objectMethod  // just to see if 'visible' within companion class

    override def receive = {
      case Stop => {

So.. that is a bit surprising. Why is there not a "special relationship" between the companion class/object allowing the class to "see" the object methods automatically?

Update I was a bit skeptical on this, and so went ahead and commented out the "import MarkerActor._" This resulted in "Symbol not found: Stop" errors in the Companion Class. So .. the import really is required.

Tetter answered 16/5, 2014 at 21:24 Comment(13)
I think it actually imports the types.Kingbolt
No, I commented out the import statement and then the case objects were marked as "Cannot resolve symbol Stop"Tetter
Stop is of type Stop.type. The Scala spec says that private members of the companion object are visible in the class, but does that include types? If types inside the companion object are not visible in the class, then you cannot use Stop because its type would be private.Kingbolt
Those include types, yes. In any case I have also shown a method "objectMethod" that displays the same visibility (/not visible) behavior.Tetter
Interesting. Apparently, a method being in the companion object just means you can access it, but it isn't automatically imported. You should be able to make objectMethod private and still call it from the class.Kingbolt
Correct - the private does not hide the companion's method from the class.Tetter
So, there's your answer: class and object have a special relationship, they can access their respective privates. However, they still need to qualify the access with the class/object name.Kingbolt
I am going to leave this question open to hear if there were more to the relationship details, to potentially get more insight here. But I will go ahead and upvote your last comment in any case.Tetter
Tobias' answer is correct. Follow the links on this thread for some additional insights from a few years back as to why this is the case. scala-lang.org/old/node/2411Affusion
Well it is Viktor Klang asking that question, so I am in good company!Tetter
So to summarize the thread from the link from @Chris: it was discussed at the "highest" level (including Odersky) and the (far-from unanimous) consensus was the auto-import of companion artifacts into the class were not preferred. It was a split decision.Tetter
@Affusion I would like to accept as the answer your post - since it goes to the heart of the decision - which was a split decision judgement call.Tetter
I just converted it to an answer for you.Affusion
A
22

Several years ago there was a discussion on whether to implicitly import all companion object members into their parent classes. The decision made at the time, which still makes sense today, was to require an explicit import, since it is easier to add an additional import than to remove an undesired one. Here is the full discussion.

Affusion answered 18/5, 2014 at 23:28 Comment(1)
the nabble link in the scala-lang.org discussion didn't work for me here is an alternative link scala-language.1934581.n4.nabble.com/…Spandau

© 2022 - 2024 — McMap. All rights reserved.