ScalaTest如何检查相等性?

时间:2015-05-08 23:57:15

标签: scala equality scalatest

我引用this

我是ScalaTest的新手,但我认为这意味着,如果我实施了==,那么这将用于解释should equal。但是,我的代码似乎与此相矛盾。

我正在通过Odersky's book - 我正在练习6.0.3。我已经实现了如上所述的自然数,并添加了相等运算符:

class Succ(x: Nat) extends Nat {
  ...
  override def ==(that:Nat): Boolean = {
    try {
      (that - this).isZero
    } catch {
      case _: Throwable => false
    }
  }
}

object Zero extends Nat {
  ...
  override def ==(that:Nat): Boolean = {
    that.isZero
  }
}

但是,以下测试用例失败:

def makeNat(n:Integer):Nat = {
  if (n < 0) throw new RuntimeException("Can't generate Nat from <0: " + n.toString())
  if (n==0) return Zero
  else return makeNat(n-1).suc
}

test("Addition is commutative") {

   val nats = for (n <- Gen.choose(0, 1000)) yield  makeNat(n)
   val p = forAll ((nats, "n1"), (nats, "n2")) {
      (n1: Nat, n2: Nat) =>
        (n1 + n2) should equal (n2 + n1) //Fails
    }

}

但是减去参数并与Zero通过比较:

test("Addition is commutative") {

  val nats = for (n <- Gen.choose(0, 1000)) yield  makeNat(n)

  val p = forAll ((nats, "n1"), (nats, "n2")) {
    (n1: Nat, n2: Nat) =>
      ((n1 + n2)-(n2+n1)) should equal (Zero) // Passes
  }

}

编辑:感谢dwickern @,这已经解决了 - 我需要为equals方法添加覆盖,而不是==方法。即:

  override def equals(that:Any): Boolean = that match {
    case that:Nat => (that-this).isZero
    case _ => false
  }

1 个答案:

答案 0 :(得分:3)

如您所知,您需要覆盖equals而不是==。 scala中的==方法调用Java的标准Object.equals,除非它正确处理null而不抛出异常。

在实践中,您不需要经常覆盖equals因为存在案例类。要使用它们,请将class更改为case class,将object更改为case object。编译器将为您实现equalshashCode。如果一个类遵循这些模式,则案例类非常适合:

  • 该类被视为值。 (绝对适用于自然数字级别!)
  • 案例类应该是不可变的。平等和可变性不会混合。
  • 避免类继承。平等+继承很复杂。改为使用特征。