Scala: Does == default to equals?

人盡茶涼 提交于 2020-01-13 09:11:11

问题


I'm reading through Programming in Scala. It says:

You can redefine the behavior of == for new types by overriding the equals method, which is always inherited from class Any. The inherited equals, which takes effect unless overridden, is object identity, as is the case in Java. So equals (and with it, ==) is by default the same as eq, but you can change its behavior by overriding the equals method in the classes you define. It is not possible to override == directly, as it is defined as a final method in class Any. That is, Scala treats == as if was defined as follows in class Any:

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

But this isn't jibing with what I'm seeing in scala 2.9.1, where it seems like:

  • == doesn't seem to default to equals
  • I can override == directly (without complaint from the compiler, no override needed).

So it seems to me like either:

  • I'm doing it wrong - this definition of Rational gives

    % 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
    
  • or I'm reading an out of date version of the book, and things have changed.

What's going on?


回答1:


You are making a very understandable mistake--you are trying to write a type-safe equals (i.e. def equals(r: Rational)) instead of a generic equals (i.e. override def equals(a: Any)).

So instead of overriding equals--note that you don't need the override keyword!--you are creating another method by overloading the type parameters, and then having two equals methods, one which takes Rational and one which takes Any. Same thing with ==; only the Any-parameterized method cannot be overridden.

To get the behavior consistent with Java (and the Scala library), you'd need to rewrite equals as something like

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


来源:https://stackoverflow.com/questions/9853645/scala-does-default-to-equals

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!