提问人:oerpli 提问时间:1/29/2018 更新时间:1/30/2018 访问量:220
类之间的自定义相等性
Custom equality between classes
问:
我目前正在学习 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)
我认为它应该像这样工作,因为运算符应该使用我希望使用最具体实现的方法(使用某个随机类调用时的默认实现,以及使用另一个作为参数调用时的实现。==
equals
Shape
所以,我的问题是:
- 如何实现?
- 是否有理由不应该实现它(例如,它与一些 OOP 原则相冲突,尽管它是传递的、反身的和对称的)
- Shape 应该是一个抽象类还是一个特征?
答:
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
请记住,如果重写等于时,也要重写哈希码,以便它们保持一致。
上一个:凿子串联错误
下一个:隐式定义集合的相等性/排序
评论