ScalaTest 如何检查相等性?
How does ScalaTest check equality?
我参考了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
}
}
但是减去参数并与零比较通过:
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
}
如您所见,您需要覆盖 equals
而不是 ==
。 scala 中的 ==
方法调用 Java 的标准 Object.equals
除了它正确处理 null 而不会抛出异常。
实际上,您不需要经常重写 equals
,因为存在 class 的情况。要使用它们,请将 class
更改为 case class
,将 object
更改为 case object
。编译器将为您实现 equals
和 hashCode
。如果 class 遵循以下模式,则 classes 非常适合:
- class 被视为一个值。 (对于自然数绝对正确class!)
- 大小写 class 应该是不可变的。平等和可变性不能混为一谈。
- 避免class继承。平等+继承很复杂。请改用特征。
我参考了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
}
}
但是减去参数并与零比较通过:
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
}
如您所见,您需要覆盖 equals
而不是 ==
。 scala 中的 ==
方法调用 Java 的标准 Object.equals
除了它正确处理 null 而不会抛出异常。
实际上,您不需要经常重写 equals
,因为存在 class 的情况。要使用它们,请将 class
更改为 case class
,将 object
更改为 case object
。编译器将为您实现 equals
和 hashCode
。如果 class 遵循以下模式,则 classes 非常适合:
- class 被视为一个值。 (对于自然数绝对正确class!)
- 大小写 class 应该是不可变的。平等和可变性不能混为一谈。
- 避免class继承。平等+继承很复杂。请改用特征。