Scala:==默认为等于?

时间:2012-03-24 17:04:03

标签: scala equality

我正在阅读Scala编程。它说:

  

您可以通过覆盖==方法重新定义equals对新类型的行为,该方法始终从类Any继承。除非被覆盖,否则继承的equals是对象标识,就像Java中的情况一样。因此,equals(以及==)默认情况下与eq相同,但您可以通过覆盖您定义的类中的equals方法来更改其行为。无法直接覆盖==,因为它被定义为类Any中的最终方法。也就是说,Scala将==视为在课程Any中定义如下:

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

但这并不是我在scala 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
    
  • 或者我正在读这本书的过时版本,事情已经发生了变化。

发生了什么事?

1 个答案:

答案 0 :(得分:21)

你犯了一个非常容易理解的错误 - 你试图写一个类型安全的等号(即def equals(r: Rational))而不是通用的等号(即override def equals(a: Any))。

所以不要覆盖equals - 请注意,您不需要override关键字! - 您正在通过重载类型参数创建另一个方法,然后使用两个< / em>等于方法,一个取Rational,另一个取Any。与==相同;只有Any - 参数化方法无法覆盖。

要使行为与Java(和Scala库)保持一致,您需要将equals重写为类似

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