1

While fighting with my private immutable class constructor, and the constraint that auxiliary constructors have to call each other as first statement, without anything else from the class in scope, I seem to be constrained to use a companion object for my instantiations, and since my companion object would have to access the main constructor, I need the private keyword to target a scope including that object.

Now, my brain is weak in name generation, and I am trying to save the need of an enclosing namespace for both that companion object and the class by placing my class within the companion object itself, this way:

object Group {
  private def complexComputeX(z: Int) = z
  private def complexComputeY(x: Int, z: Int) = x + z
  def apply(z: Int) = {
    val x = complexComputeX(z)
    val y = complexComputeY(x, z)
    new Group(x, y)
  }
  class Group private[Group](x: Int, y: Int) {
    //...
  }
}
val x = Group(5)
//...

The problem is that the Group of private[Group] does not reference the object, but still the class (making it superfluous).

How can I tag that constructor to be available at the companion object level, but not outside it?

PS: that companion object is already giving me headache, and I would even have preferred to have just the class, en-scoping there the complexCompute, which several constructors implementations could need...

EDIT: Okay. Just while adding the tags I hit a neuron ringing me that a companion object might have some privilege over the class' scope. It can access its private parts, and so I can simply have object and class side to side without dedicated enclosing scope. However, I maintain the question, for both a response on possibility way to handle scoping for such boxing cases object Main {object Main {object Main... and for chances of remarks about techniques for having only constructors in the class without any companion object.

Nirvana
  • 93
  • 1
  • 6
  • Changed the question from originally "How can we reference the outer scope in Scala?". I guess I would ask it separately if ever I find another reason to try (and my bet is that there would not be a way to specify precisely the private level when levels have the same name). – Nirvana Dec 13 '14 at 22:05

2 Answers2

3

Your Group object is not the companion object of your Group class as they are not in the same namespace.

You don't have to provide a scope to the private modifier. If you leave it empty, it's only accessible by this class and its companion object.

object Something {

  class Group private(x: Int, y: Int)
  object Group {
    private def complexComputeX(z: Int) = z
    private def complexComputeY(x: Int, z: Int) = x + z
    def apply(z: Int) = {
      val x = complexComputeX(z)
      val y = complexComputeY(x, z)
      new Group(x, y)
    }
  }
  val x = Group(5)

  // This line doesn't compile
  new Group(42, 45)
}
Dimitri
  • 1,786
  • 14
  • 22
  • Ah, right, thank you. Just as I posted my edit. I am still interested to know if ever we can handle nested levels with the same name. – Nirvana Dec 05 '14 at 19:36
0

The companion object's private are also accessible from the class, so I have this other option, concerning my root problem:

object Group {
  private def computeX(z: Int) = z
  private def computeY(x: Int, z: Int) = x + z
  private def computeXY(z: Int) = {
    val x = computeX(z)
    (x, computeY(x, z))
  }
}
class Group private (x: Int, y: Int) {
  private def this(xy: (Int, Int)) = this(xy._1, xy._2)
  def this(z: Int) = this(Group.computeXY(z))
}
val group = new Group(5)

That the companion object makes a full privatable scope available from my constructors makes me breath better. In my full case I was indeed also going to need types I wanted private too. The fact that I am forced to create a companion to contain this locally useful scope might not be so important now, I guess. However, the use of the tuple makes it more cumbersome than Dimitri's option.

Nirvana
  • 93
  • 1
  • 6