简体   繁体   中英

Can I in Scala declare the class inside its companion object?

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.

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)
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM