views:

93

answers:

2

I'm working on a homework assignment for my object oriented design class, and I'm running into trouble with Scala's companion objects. I've read in a few places that companion objects are supposed to have access to their companion class's private methods, but I can't seem to get it to work. (Just as a note, the meat of the assignment had to do with implementing a binary search tree, so I'm not just asking for answers...)

I have an object that is supposed to create an instance of my private class, BstAtlas (Bst is also defined in the Atlas object, took it out for clarity):

object Atlas {                                             
  def focusRoom(newRoom:Room,a:Atlas):Atlas = a.helpFocusRoom(newRoom);

  abstract class Atlas {
    ...
    protected def helpFocusRoom(n:Room):Atlas;
    ...
  }

  private class BstAtlas(bst:Bst) extends Atlas {
    ...
    protected def helpFocusRoom(newRoom:Room):Atlas = ...
       // uses some of bst's methods
    ...
  }
}

But when I go to compile, I get the following error:

Question23.scala:15: error: method helpFocusRoom cannot be accessed in Atlas.Atlas a.helpFocusRoom(newRoom);

The function helpFocusRoom needs to be hidden, but I don't know how to hide it and still have access to it inside of the companion object.

Can anyone tell me what I'm doing wrong here?

+7  A: 

The problem is that classes and companion objects can't be nested like that. To define a companion object, you need to define the class outside of the object's body but in the same file.

Dave Griffith
Thanks, that does it. The professor told us in lecture to use the nested way up above to hide implementation details... But this way seems to have the same result (and compiles, which is a plus).
Shaun
+2  A: 

Companion objects should be next to their real object, not containing it:

object Example {
  class C(val i: Int = C.DefaultI) { }
  object C { protected val DefaultI = 5 }
}

scala> (new Example.C).i
res0: Int = 5

scala> Example.C.DefaultI
<console>:11: error: value DefaultI cannot be accessed in object Example.C
   Example.C.DefaultI

Alternatively, you can alter the scope of the protected keyword to include the enclosing object:

object Example {
  def value = (new D).hidden
  class D(val i: Int = 5) {
    protected[Example] def hidden = i*i
  }
}

scala> Example.value
res1: Int = 25

but here you ought not name the outer object the same thing as the inner class or you'll have trouble referring to it from within the class.

Rex Kerr