7

我知道==Scala 中的方法与 Java 中的 equals 方法具有相同的语义。但是,我想了解何时应用于递归结构的实例。例如,考虑一堆表达式:

abstract class Exp

abstract class BinaryExp(l:Exp, r:Exp) extends Exp

case class Plus(l:Exp, r:Exp) extends BinaryExp(l,r)

case class Minus(l:Exp, r:Exp) extends BinaryExp(l,r)

case class Mult(l:Exp, r:Exp) extends BinaryExp(l,r)

case class Div(l:Exp, r:Exp) extends BinaryExp(l,r)

case class Num(v:Int) extends Exp

那么,当我有两个实例 aBinaryExp时,比如说obj1and obj2,是否会obj1 == obj2导致深度(递归)相等测试?也就是说,是否保证 ifobj1 == obj2成立,然后obj1obj2表示相同的精确表达式树?

请注意,在所有类中,我都依赖于==(它不会在任何地方被覆盖)的默认实现。

4

1 回答 1

14

这很容易测试自己:

val x = Plus(Num(1), Num(2))
val y = Plus(Num(1), Num(2))
val z = Plus(Num(1), Num(3))

println(x == y) // prints true
println(x == z) // prints false

这些给出正确答案的事实表明相等性检查正在检查子表达式的“深度”相等性。

此外,您可以在文档中看到:

对于每个案例类,Scala 编译器都会生成实现结构相等的 equals 方法

“结构相等”是您想知道的那种深度相等检查。

最后,如果你真的想看看语法糖之外发生了什么,你可以-xPrint:typer在运行scalac或启动 REPL 时使用该选项。如果您将该选项与 REPL 一起使用,然后声明 class Plus,您会得到以下结果(缩短):

scala> case class Plus(l:Exp, r:Exp) extends BinaryExp(l,r)
[[syntax trees at end of typer]]// Scala source: <console>
...
case class Plus extends $line2.$read.$iw.$iw.BinaryExp with ScalaObject with Product with Serializable {
  ...
  override def equals(x$1: Any): Boolean = Plus.this.eq(x$1.asInstanceOf[java.lang.Object]).||(x$1 match {
    case (l: $line1.$read.$iw.$iw.Exp, r: $line1.$read.$iw.$iw.Exp)$line3.$read.$iw.$iw.Plus((l$1 @ _), (r$1 @ _)) if l$1.==(l).&&(r$1.==(r)) => x$1.asInstanceOf[$line3.$read.$iw.$iw.Plus].canEqual(Plus.this)
    case _ => false
  });

所以,埋在第一个case你会看到它是为了检查平等Plus.equals而调用的。if l$1.==(l).&&(r$1.==(r))换句话说,case 类的生成相等方法调用==它的子表达式来检查它们的相等性。

于 2012-08-09T21:53:29.870 回答