2012-08-09 61 views
7

我知道Scala中的==方法與Java中的equals方法具有相同的語義。但是,我想了解何時應用於遞歸結構的實例。 例如,考慮了一堆表情:遞歸定義類型中的Scala和==方法

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代表相同的確切表達式樹嗎?

請注意,在所有類中,我依賴==的默認實現(它不會在任何地方覆蓋)。

回答

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是看:它實現結構相等

對於每個case類,Scala編譯器生成equals方法

「結構平等」是什麼樣的深入的平等檢查,你想知道。

最後,如果您確實想看看語法糖上發生的情況,那麼在運行scalac或啓動REPL時可以使用選項-xPrint:typer。如果使用該選項與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類的生成的相等方法在其子表達式上調用==來檢查它們的相等性。