使用 Scala 案例对象中的超类 require 子句



我有下面的 Scala 代码,我想在其中使用来自 case 对象的超类require子句,其中 require 中使用的参数被覆盖:

sealed abstract class C(val i: Int) {
  protected val min: Int = 1
  protected val max: Int = 5
  require(i >= min && i <= max,
    s"$i should be between $min and $max, inclusive")
}
case object O extends C(3) {
  override protected val min: Int = 3
  override protected val max: Int = 5
}
println(O)

但是,打印O给了我java.lang.IllegalArgumentException: requirement failed: 3 should be between 0 and 0, inclusive例外。

仅覆盖其中一个参数:

case object O extends C(3) {
  override protected val max: Int = 5
}

导致异常java.lang.IllegalArgumentException: requirement failed: 3 should be between 1 and 0, inclusive

对我来说,这表明在 case 对象中的参数被覆盖之前调用了超类的require,但不知何故编译器"知道"将会发生覆盖,并且它采用参数数据类型的默认值,在本例中为零。

为什么会这样,当对象中的参数被覆盖时,如何使用 case 对象中的超类参数化require子句?

你对执行和初始化顺序的假设是正确的。

要解决此问题,您有几种不同的选择。一种是使每个val都被覆盖为lazy val,如下所示:

sealed abstract class C(val i: Int) {
  protected lazy val min: Int = 1
  protected lazy val max: Int = 5
  require(i >= min && i <= max,
    s"$i should be between $min and $max, inclusive")
}
case object O extends C(3) {
  override protected lazy val min: Int = 3
  override protected lazy val max: Int = 5
}

另一种方法是在重写时使用"早期定义"语法。abstract class代码保持不变,但object如下所示。

case object O extends {
  override protected val min: Int = 3
  override protected val max: Int = 5
} with C(3)

第三种选择是使用"常量值定义",但这往往更麻烦且不太方便。

有关所有三个选项的详细信息,请参阅此常见问题解答。

最新更新