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

lec*_*eco 7 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
Run Code Online (Sandbox Code Playgroud)

然后,当我有两个a的实例时BinaryExp,说obj1obj2,确实会obj1 == obj2导致深度(递归)相等性测试?也就是说,它保证如果obj1 == obj2成立,则obj1obj2表示相同的精确表达式树?

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

dhg*_*dhg 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
Run Code Online (Sandbox Code Playgroud)

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

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

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

"结构平等"是你想知道的那种深刻的平等检查.

最后,如果你真的想看看语法糖之外发生了什么,你可以-xPrint:typer在运行scalac或启动REPL 时使用该选项.如果您将该选项与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
  });
Run Code Online (Sandbox Code Playgroud)

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