我知道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
的两个实例,比如obj1
和obj2
时,obj1 == obj2
会导致深度(递归)相等测试吗?也就是说,是否保证如果obj1 == obj2
成立,那么obj1
和obj2
代表相同的表达式树?
请注意,在所有类中,我依赖于==
的默认实现(它不会在任何地方被覆盖)。
答案 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类的等式方法在其子表达式上调用==
来检查它们的相等性。