Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't the members of my nested companion object automatically visible in the class?

Suppose I have this Scala code:

object Outer {

  object Inner {
    val B = "B"
  }
  class Inner {
    def b = B
  }
}

I would expect this to compile, but B cannot be accessed from the definition of b. I need to add import Inner._ in class Innerto make it work. Why is that? Is the companion object Inner not defined correctly?

like image 244
Jean-Philippe Pellet Avatar asked Nov 25 '10 10:11

Jean-Philippe Pellet


2 Answers

If the members of the companion object would be imported into the class, it would pollute the namespace of the class without the programmer being able to controle it. This might not be that bad (but still bad) with values but I really wouldn't want to see that with functions.

Just think about apply() or functions you inherit from traits (both cases where you can't just change the name without loosing something). If these functions where automatically imported into your classes namespace, the compiler wouldn't know which one to use. So if the class and the object had a function func() you would end up writing this.func() in your classes code just to make sure which one to call.

So see it as a possibility to keep your namespace clean. You can still pollute it by using import Inner._

like image 170
Agl Avatar answered Sep 19 '22 15:09

Agl


It's just not supposed to work this way - using import Inner._ is a consistent behavior.


Generally, companion object is needed, if you want to achieve the behavior similar to static members in Java. Scala way is to move all static members away to a singleton object, with the benefit that private/protected memebers of a companion class can be accessed from it:

object Outer {

  object Inner {
    def print(inner: Inner) = inner.B // compiles!
  }    
  class Inner {
    private val B = "B"
  }    
}

You can use companion object as a factory for the class with a private constructor:

scala> object Outer {
     |
     |   object Inner {
     |     def newInstance = new Inner()
     |   }
     |   class Inner private() {
     |     private val B = "B"
     |   }
     | }
defined module Outer

scala> Outer.Inner.newInstance
res1: Outer.Inner = Outer$Inner@431693

scala> new Outer.Inner
<console>:7: error: constructor Inner cannot be accessed in object $iw
       new Outer.Inner
       ^
like image 23
Vasil Remeniuk Avatar answered Sep 19 '22 15:09

Vasil Remeniuk