简体   繁体   English

将正在构造的实例传递给案例类构造函数

[英]Pass to a case class constructor the instance being constructed

I have a complex set of traits and case classes, but for the sake of the discussion let me summarize what I'm trying to model in this way:我有一组复杂的特征和案例类,但为了讨论起见,让我总结一下我试图以这种方式建模的内容:

case class X(x: X)

That's fine until I end up initializing one of the instances this way:这很好,直到我最终以这种方式初始化其中一个实例:

val myX: X = X(myX)

It compiles (unbelievably), but the myX passed to the constructor is actually null , easily visible by checking myX.x afterwards.它编译(令人难以置信),但传递给构造函数的myX实际上是null ,之后通过检查myX.x很容易看到。

Suppose having an instance pointing to itself is fine for what I'm trying to model, is there an elegant way to solve this issue and have the new instance of X with a pointer to itself?假设有一个指向自身的实例对于我想要建模的内容来说很好,有没有一种优雅的方法来解决这个问题,并让X的新实例带有一个指向自身的指针? I mean without mutating the object after its creation, nor introducing a 2nd constructor that takes no parameter and uses this inside.我的意思是没有在创建后改变对象,也没有引入不带参数并在内部使用this的第二个构造函数。 Remember please the real situation is more complex that what sketched here.请记住,实际情况比这里描述的要复杂。

If you need to have a case class, I don't think it can be done.如果你需要一个案例类,我认为它不能完成。 Case classes cannot have lazy parameters, and if they could point to themselves most of their methods would probably blow the stack. Case 类不能有惰性参数,如果它们可以指向自己,那么它们的大部分方法可能会炸毁堆栈。 With a regular class you can do this:通过常规课程,您可以这样做:

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

If you want case class-like behavior you'll have to implement the boilerplate (apply, unapply, copy, equals, hashcode, ...) yourself, and be very careful not to trigger an infinite loop or a stack overflow.如果您想要类似案例类的行为,您必须自己实现样板(应用、取消应用、复制、等于、哈希码等),并且要非常小心,不要触发无限循环或堆栈溢出。

Ill-advisedly, consider "simulating" by-name parameters in case classes like so不明智的做法是,在这样的案例类中考虑“模拟”按名称参数

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

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

however note the warning by Jasper-M.但是请注意 Jasper-M 的警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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