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