Reputation: 93
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.
Upvotes: 1
Views: 285
Reputation: 93
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.
Upvotes: 0
Reputation: 1786
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)
}
Upvotes: 3