6

I'm wondering, why can't a class get an access to a companion object's field?

class MyClass {
  println(val1) // not found, why?
}

object MyClass {
  val val1 = "str"
}

It should, it should even have an access to the private fields of object MyClass.

giampaolo
  • 6,906
  • 5
  • 45
  • 73
Incerteza
  • 32,326
  • 47
  • 154
  • 261

2 Answers2

10

You can do that by using MyClass.val1 instead of just val1. I guest that's done to denote that companion object members can be accessed from anywhere (with default modifiers).

kompot
  • 798
  • 6
  • 8
  • it should not be so because it's a companion object. – Incerteza Nov 20 '13 at 18:08
  • 1
    @Alex: I guess that's by design and was reasoned along the lines of this comment: "The thing is, it's a lot easier to import something into your namespace if you want it than it is to unimport if you don't. And personally I already have enough problems with shadowing" (from http://www.scala-lang.org/old/node/2411.html#comment-8493). If you think so because you are reading "Programming in Scala", you might just have misunderstood it (see comment http://www.scala-lang.org/old/node/2411.html#comment-8427). – Roland Ewald Nov 20 '13 at 18:20
  • hasn't that been differently recently? I think I have used it without importing previously. – Incerteza Nov 20 '13 at 18:24
  • @Alex: you could just import companion object's methods like this: `class MyClass { import MyClass._; println(val1) }`; – senia Nov 20 '13 at 19:47
  • @senia, my last question is not about that. Of course, I can do that, but the object doesn't necessarily have to be a companion object. – Incerteza Nov 21 '13 at 03:21
  • @senia, and since it's a companion object, it shouldn't require importing itself to "companion" class. – Incerteza Nov 22 '13 at 12:16
  • @Alex: why not? There could be methods with the same name in object and class. For instance: `List.apply(1).apply(0)`. Importing by default leads to name collisions. – senia Nov 22 '13 at 12:26
  • @senia, has that always been so? If I recall correctly, previously there wasn't a need to import the fields of a companion object, they were accessible by default. – Incerteza Nov 24 '13 at 06:13
  • @Alex: the oldest scala version [available](http://www.scala-lang.org/download/all.html) on `scala-lang.org` is [`2.5.0.final`](http://scala-lang.org/download/2.5.0.final.html). And you have to import companion object methods manually in that version. – senia Nov 24 '13 at 08:06
  • @Alex: you could see all changes about companion objects in [Changelog](http://www.scala-lang.org/download/changelog.html). The only change about companion object was in `Version 2.1.8 (23-Aug-2006)` [Relaxation of Private Access](http://www.scala-lang.org/download/changelog.html#relaxation_of_private_access). Before that version you couldn't even call private methods of companion object in class. – senia Nov 24 '13 at 08:20
6

It's debatable that a class "should" have access to its companion object fields by default. Consider the not uncommon case where the companion object's apply method is used as a factory, and the object itself has an apply method to do something different. It would get confusing to read the code and know which method was meant! Roland Ewald made a comment to another answer quoting http://www.scala-lang.org/old/node/2411.html#comment-8493 which sums it up nicely:

"The thing is, it's a lot easier to import something into your namespace if you want it than it is to unimport if you don't. And personally I already have enough problems with shadowing."

And that gives the answer. Use import thus:

class MyClass {
  import MyClass._
  println(val1) // Should see it now!
}

object MyClass {
  val val1 = "str"
}
Community
  • 1
  • 1
pndc
  • 3,710
  • 2
  • 23
  • 34