递归定义类型中的Scala和==方法

时间:2012-08-09 21:48:13

标签: scala

我知道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

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

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

1 个答案:

答案 0 :(得分: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

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

此外,您可以在documentation中看到:

  

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

“结构平等”是你想知道的那种深刻的平等检查。

最后,如果你真的想看看语法糖之外发生了什么,你可以在运行-xPrint:typer或启动REPL时使用选项scalac。如果您将该选项与REPL一起使用,然后声明类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类的等式方法在其子表达式上调用==来检查它们的相等性。