Scala:==默认为等于?

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

但这并不是我在scala 2.9.1中看到的内容,它看起来像:

  • == 似乎没有默认 equals
  • 我可以==直接覆盖(没有编译器的抱怨,override不需要).

所以在我看来似乎要么:

  • 我做错了 - 这个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
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者我正在阅读这本书的过时版本,事情已经发生了变化.

这是怎么回事?

Rex*_*err 21

您正在犯一个非常容易理解的错误 - 您正在尝试编写类型安全等于(即def equals(r: Rational))而不是通用等号(即override def equals(a: Any)).

所以不要覆盖equals- 注意你不需要override关键字! - 你是通过重载类型参数创建另一个方法,然后有两个等于方法,一个采取Rational,一个采取Any.同样的事情==; 只有Any-parameterized方法不能被覆盖.

要获得与Java(和Scala库)一致的行为,您需要将equals重写为类似的东西

override def equals(a: Any) = a match {
  case r: Rational => numer == r.numer && denom == r.demon
  case _ => false
}
Run Code Online (Sandbox Code Playgroud)

  • @rampion - 不,你必须完全匹配类型签名.`equals:Any => Boolean`表示它返回一个函数(即`Function1 [Any,Boolean]`类的实例).尽管从某种意义上说这在概念上是等同的,但它并不是完全相同的方法,所以它不起作用. (2认同)