Передайте конструктору класса case конструируемый экземпляр - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть сложный набор характеристик и классов дел, но ради обсуждения позвольте мне обобщить то, что я пытаюсь смоделировать следующим образом:

case class X(x: X)

Это нормально, пока я не закончу инициализировать один из экземпляров следующим образом:

val myX: X = X(myX)

Он компилируется (невероятно), но myX, переданный конструктору, на самом деле null , легко видимый после проверки myX.x впоследствии .

Предположим, наличие экземпляра, указывающего на себя, хорошо для того, что я пытаюсь смоделировать, есть ли элегантный способ решить эту проблему и получить новый экземпляр X с указателем на себя? Я имею в виду не мутировать объект после его создания и не вводить 2-й конструктор, который не принимает параметров и использует this внутри. Помните, пожалуйста, реальная ситуация более сложна, чем то, что было показано здесь.

Ответы [ 2 ]

6 голосов
/ 06 февраля 2020

Если вам нужен класс кейсов, я не думаю, что это можно сделать. Классы case не могут иметь ленивых параметров, и если бы они могли указывать на себя, большинство их методов, вероятно, взорвало бы стек. С обычным классом вы можете сделать это:

scala> class X(x0: =>X) {
     |   lazy val x = x0 
     | }
class X

scala> val x: X = new X(x)
val x: X = X@5f98cb6f

scala> x.x
val res0: X = X@5f98cb6f

scala> x.x.x
val res1: X = X@5f98cb6f

Если вам нужно поведение, подобное классу case, вам придется реализовать шаблон (применить, отменить, скопировать, равно, хэш-код, ...) самостоятельно и будьте очень осторожны, чтобы не вызвать бесконечное l oop или переполнение стека.

2 голосов
/ 06 февраля 2020

Опрометчиво, рассмотрите возможность "имитации" параметров по имени в таких классах, например, как

case class X(v: () => X) {
  def x: X = v.apply
}

val myX: X = X(() => myX)

, однако обратите внимание на предупреждение Jasper-M.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...