【问题标题】:Scala: Is my `equals` method correct?Scala:我的“equals”方法正确吗?
【发布时间】:2015-12-13 13:13:07
【问题描述】:

我为A 类写了一个equals 方法。

class A(x: Int, s: String) {
  override def equals(that: Any) = that match {
    case a: A => this.x == a.x && this.s == a.s
    case _    => false
  } 
}

对吗?

【问题讨论】:

  • 我刚刚发布了另一个问题的答案,这是对您问题的更详细的答案。对于您的类实例来说,正确实现equalshashCode 以在Scala 集合库中正常运行至关重要。或者遭受意想不到的失败。 stackoverflow.com/a/56509518/501113

标签: scala


【解决方案1】:

是的,这是正确的。但是,您还应该覆盖 hashCode 方法以反映相等性。也就是说,如果您有两个实例ab,其中a == b,您应该确保a.hashCode == b.hashCode

实现两者最简单的方法是使用案例类:

case class A(private val x: Int, private val s: String)

这会为您提供正确的 equalshashCode “免费”。


如果您计划存在A 的子类的可能性,您可以查看Odersky 的idea of canEqual(也称为here)。

【讨论】:

  • 感谢您的回答!
【解决方案2】:

更好的方法是在 A 的伴随对象上定义一个 Ordering[A] 实例。

object A{
    implicit object aOrdering extends Ordering[A]{
        override def compare(x:A,y:A):Int = ......
    }
}

比你应该写的等于方法:

override def equals(that: Any) = that match {
  case a: A => {
        val ordering = implicitly[Ordering[A]] 
        ordering.compare(this,a) == 0 
 }
  case _    => false
} 

通过这种方式,您可以重用您的代码,即 scala 集合和您需要为此类排序的其他地方。

【讨论】:

  • 为什么不按通常的方式编写它并在compare 方法中利用类的equals 方法?您必须在一处或另一处编写相等定义。对于没有逻辑顺序的类,您不能使用Ordering 对象,因此在任何地方以正常方式编写它似乎更加一致。我看不出你的方式有任何优势,而且看起来更复杂和不一致。我错过了什么?
  • 如果你没有排序,它的权利只覆盖equals()。如果您确实有 Ordering,则您有重复的代码,这意味着您需要同时维护它们
  • 为什么,重复代码在哪里?您的compare 方法应该只使用该类定义的equals 方法来确定何时吐出0。没有重复。
  • 是否会出现重复代码取决于compare方法是如何实现的。一般来说,这肯定不是更好的方法(在这种情况下,实现Ordered,而不是创建隐式Ordering)。
  • 您将在 equals() 和 Ordered/Ordering 实现上复制代码。下单了?!?假设您想要多种类型的排序,即字符串的排序可以是字母顺序/字符串长度。使用 Ordered,您会遇到一个实现,另一方面,您可以为同一个类拥有多个 Ordering 实例,并且您可以根据代码的上下文选择您的 Odering 实现。更好的灵活性。请阅读 TypeClasses。
猜你喜欢
  • 1970-01-01
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 2012-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多