【问题标题】:Scala: Does == default to equals?Scala:== 默认是否等于?
【发布时间】:2012-04-08 20:46:37
【问题描述】:

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

您可以通过重写始终从类Any 继承的equals 方法来为新类型重新定义== 的行为。继承的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
    
  • 或者我正在阅读这本书的过期版本,并且情况发生了变化。

发生了什么事?

【问题讨论】:

    标签: scala equality


    【解决方案1】:

    您犯了一个非常容易理解的错误——您试图编写类型安全的等号(即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
    }
    

    【讨论】:

    • 太棒了。每次我回到 JVM 领域时,这都会让我很痛苦。我迟早会学会的。无论如何我可以放弃a match 并分配equals 一个匿名函数吗? override def equals : Any => Boolean = { case r : Rational /* ... */ } 不太好用……
    • @rampion - 不,您必须完全匹配类型签名。 equals: Any=>Boolean 表示它返回一个函数(即 Function1[Any,Boolean] 类的实例)。尽管这在某种意义上在概念上是等价的,但它并不是完全相同的方法,所以它不会起作用。
    猜你喜欢
    • 2010-12-26
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 1970-01-01
    相关资源
    最近更新 更多