簡體   English   中英

Scala 中的類的初始化如何工作?

[英]How does the initialization of classes in Scala work?

下面的代碼會拋出java.lang.NullPointerException ,因為過早地初始化了 trait。

trait DummyTrait {
  def intSeq: Seq[Int]
  require(intSeq.exists(_ > 2))
}
object Dummy extends DummyTrait {
  val extraIntSeq: Seq[Int] = Seq(-2,-3)
  override def intSeq = Seq(1,0,4) ++ extraIntSeq
}

Dummy.intSeq

但是,下面的簡單更改解決了這個問題,但我不明白為什么。

trait DummyTrait {
  def intSeq: Seq[Int]
  require(intSeq.exists(_ > 2))
}
object Dummy extends DummyTrait {
  lazy val extraIntSeq: Seq[Int] = Seq(-2,-3) // using `def` also works
  override def intSeq = Seq(1,0,4) ++ extraIntSeq
}

Dummy.intSeq

我發現this documentation about overriden val is NULL ,但它似乎不適用於上面的示例,因為修復不涉及在超類的接口中定義的變量。

另外,上面提出的解決方案是反模式嗎? 作為正在開發該特征的人,我應該如何強制執行抽象值的要求,而不會讓使用潛在NullPointerException實現子 class 的用戶感到驚訝?

觀察:我正在使用 Scala 版本 2.13.0

在第一種情況下,在調用超級構造函數之后,在構造函數中初始化了extraIntSeq ,因此 NPE

  object Dummy extends DummyTrait {
    private[this] val extraIntSeq: Seq = _;
    ...
    def <init>($outer: O): Dummy.type = {
      Dummy.super.<init>();
      Dummy.this.extraIntSeq = ... // note that it comes AFTER super
      ()
    }
  }

而在后者中,惰性 val 變成了方法。

到目前為止,您可以使用早期初始化程序

object Dummy extends {
  val extraIntSeq: Seq[Int] = Seq(-2,-3)
  override val intSeq = Seq(1,0,4) ++ extraIntSeq
} with DummyTrait

在 Scala 中,什么是“早期初始化程序”?

https://dotty.epfl.ch/docs/reference/dropped-features/early-initializers.html

https://contributors.scala-lang.org/t/proposal-to-remove-early-initializers-from-the-language/2144

https://github.com/scala/scala-dev/issues/513

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM