类之间的自定义相等性

Custom equality between classes

提问人:oerpli 提问时间:1/29/2018 更新时间:1/30/2018 访问量:220

问:

我目前正在学习 Scala,过去几年没有编程太多,所以我可能忘记了一些 OOP 基础知识。

我正在尝试实现这两个类:

case class Rectangle(a : Int,b : Int) extends Shape
case class Square(a : Int) extends Shape

trait/abstract类(我都尝试了,都不起作用)定义如下:Shape

trait Shape {
  def a : Double
  def b : Double 
  def area = a *b
  def sides = 4
  def perimeter = 2 * (a+b)

  def equals(r: Shape){
    r.a == this.a && r.b == this.b
  } 
}

所需的行为是Rectangle(2,2) == Square(2)

我认为它应该像这样工作,因为运算符应该使用我希望使用最具体实现的方法(使用某个随机类调用时的默认实现,以及使用另一个作为参数调用时的实现。==equalsShape

所以,我的问题是:

  • 如何实现?
  • 是否有理由不应该实现它(例如,它与一些 OOP 原则相冲突,尽管它是传递的、反身的和对称的)
  • Shape 应该是一个抽象类还是一个特征?
Scala OOP 平等

评论


答:

0赞 Can 1/29/2018 #1

您需要在 中重载运算符,而不是重写方法。equals==Shape

有关运算符重载的更多信息,请参阅下文。

https://docs.scala-lang.org/tour/operators.html

编辑:

显然,我最初的答案还不够清楚。请参阅以下示例:

  abstract class Shape(val a: Int, val b: Int) {
    def ==(other: Shape): Boolean = this.a == other.a && this.b == other.b
  }

  class Square(s: Int) extends Shape(s, s)
  class Rectangle(x: Int, y: Int) extends Shape(x, y)

  def main (args: Array[String] ): Unit = {
    println(new Square(2) == new Rectangle(2, 2))  // true
    println(new Square(2) == new Rectangle(4, 2))  // false
    println(new Square(2).equals(new Rectangle(4, 1))) // false
  }

评论

0赞 oerpli 1/29/2018
我认为这是完全错误的。我发现的所有内容都指出“==”回退到该方法上。您的链接也不包含与所提问题相关的任何内容。equals(x : Any)
1赞 oerpli 1/30/2018
事实上,它似乎有效。虽然这里的幻灯片 #10 slideshare.net/knoldus/object-equality-inscala 似乎建议不要这样做。此外,我还更改了您的方法以反映问题中预期的平等性。
0赞 Can 1/30/2018
@oerpli正如幻灯片所述,这是一个不鼓励的功能,因为它使代码难以阅读。我试图向你展示如何做到这一点。我建议您创建另一种方法,例如“比较”等,而不是覆盖运算符。==
1赞 oerpli 1/29/2018 #2

我找到了这组解决问题的幻灯片(至少回答了我的第一个问题):https://www.slideshare.net/knoldus/object-equality-inscala(第 9 页)

问题似乎是有必要重写内置的 equals 方法,而不仅仅是添加额外的重载。

override def equals(other : Any) : Boolean = other match{
  case s: Shape => s.a == this.a && s.b == this.b
  case _ => false
}

到目前为止,在我的测试中,这可以按预期工作。

在第 13 张幻灯片中,它提到“equals”应该只返回 true,如果它们的哈希码也相同(事实并非如此)。

评论

0赞 puhlen 1/30/2018
请记住,如果重写等于时,也要重写哈希码,以便它们保持一致。