Могу ли я в Scala объявить класс внутри объекта-компаньона?

Во время борьбы с моим личным неизменяемым конструктором класса и ограничением, которое вспомогательные конструкторы должны вызывать друг друга в качестве первого оператора, без чего-либо еще из класса в области видимости, я, похоже, вынужден использовать объект-компаньон для моих экземпляров, и так как мой объект-компаньон должен был бы получить доступ к главному конструктору, мне нужно ключевое слово private для нацеливания на область действия, включающую этот объект.

Теперь мой мозг слаб в генерации имен, и я пытаюсь избавить от необходимости заключать в себе пространство имен как для этого объекта-компаньона, так и для класса, поместив мой класс в сам объект-компаньон следующим образом:

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)
//...

Проблема в том, что Group из private[Group] не ссылается на объект, но все же на класс (делая его лишним).

Как я могу пометить этот конструктор, чтобы он был доступен на уровне объекта-компаньона, но не за его пределами?

PS: этот объект-компаньон уже вызывает у меня головную боль, и я бы даже предпочел иметь только класс, определяя complexCompute, что может потребоваться для реализации нескольких конструкторов...

РЕДАКТИРОВАТЬ: Хорошо. Просто добавляя теги, я нажимаю на нейрон, звонящий мне, что объект-компаньон может иметь некоторую привилегию над областью действия класса. Он может получить доступ к своим частным частям, и поэтому я могу просто располагать объект и класс из стороны в сторону без выделенной области видимости. Тем не менее, я сохраняю вопрос, как для ответа на возможность способа справиться с ограничением для таких случаев бокса object Main {object Main {object Main... и для шансов на замечания о способах иметь только конструкторов в классе без какого-либо сопутствующего объекта.

2 ответа

Решение

Ваш объект Group не является сопутствующим объектом вашего класса Group, поскольку они не находятся в одном и том же пространстве имен.

Вам не нужно предоставлять рамки для private модификатор. Если вы оставите его пустым, он будет доступен только этому классу и его сопутствующему объекту.

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

Приватное объекта-компаньона также доступно из класса, поэтому у меня есть еще один вариант, касающийся моей корневой проблемы:

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)

То, что объект-компаньон делает доступным полный объем доступной информации от моих конструкторов, заставляет меня дышать лучше. В моем полном случае я действительно нуждался в типах, которые я тоже хотел в частном порядке. Думаю, тот факт, что я вынужден создать компаньона, который будет содержать эту локально полезную область, может быть не таким уж важным. Тем не менее, использование кортежа делает его более громоздким, чем вариант Дмитрия.

Другие вопросы по тегам