2012-03-24 95 views
7

我正在閱讀通過在斯卡拉編程。它說:Scala:==默認等於?

您可以通過重寫equals方法,它總是從Any類繼承的重新定義的==新類型的行爲。繼承的equals,除非被重寫,否則它是對象標識,就像Java中的情況一樣。因此equals(和它,==)默認情況下與eq相同,但您可以通過在您定義的類中覆蓋equals方法來更改其行爲。無法直接覆蓋==,因爲它被定義爲類Any中的最終方法。也就是說,斯卡拉把==彷彿被定義爲Any類如下:

final def == (that: Any): Boolean = 
    if (null eq this) (null eq that) else (this equals that) 

但是這不是我所看到的斯卡拉2.9.1,它好像絕塵而去:

  • ==似乎並不默認爲equals
  • 我可以(從編譯器無投訴,無override需要)直接覆蓋==

所以,在我看來,像之一:

  • 我做錯了 - this definition of Rational

    % scala                 
    Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29). 
    Type in expressions to have them evaluated. 
    Type :help for more information. 
    
    scala> Rational(1) == Rational(1) 
    res0: Boolean = false 
    
    scala> Rational(1) equals Rational(1) 
    res1: Boolean = true 
    
  • 或我讀的出來的最新版本書,事情變了。

發生了什麼事?

回答

21

您正在犯一個非常容易理解的錯誤 - 您正試圖編寫類型安全的等號(即def equals(r: Rational))而不是通用等號(即override def equals(a: Any))。

所以不是壓倒一切的equals - 注的,你不需要override關鍵詞 - !你是通過重載型參數創建另一個方法,然後有 equals方法,其中一個需要Rational和一個這需要Any。與==一樣的東西;只有Any-參數化的方法不能被覆蓋。

要獲得的行爲與Java(和Scala庫)一致,你需要重寫等於,就像這樣

override def equals(a: Any) = a match { 
    case r: Rational => numer == r.numer && denom == r.demon 
    case _ => false 
} 
+0

真棒。每當我回到JVM的土地時,這都會讓我感到痛苦。我遲早會了解它。無論如何,我可以放棄'一個匹配',只是將'equals'分配給一個匿名函數? 'override override def equals:Any => Boolean = {case r:Rational/* ... * /}'不起作用... – rampion 2012-03-24 17:32:50

+2

@rampion - 不需要,您必須完全匹配類型簽名。 'equals:Any => Boolean'表示它返回一個函數(即Function1 [Any,Boolean]類的一個實例)。儘管這在概念上是相同的,但它不是完全相同的方法,所以它不起作用。 – 2012-03-24 17:38:16