case caseinheritance的* so *错误是什么?
在寻找别的东西的时候,很偶然的,我偶然发现了一些关于恶意案例类inheritance的评论。 有这样的东西,叫做ProductN
,可怜的人,国王,精灵和巫师,以及某种非常理想的财产如何失去案例类inheritance。 那么case类inheritance有什么问题呢?
一个字: 平等
case
类提供了equals
和hashCode
的提供的实现。 等价关系,称为equals
这样(即必须具有以下属性):
- 对于所有的
x
;x equals x
是true
(反身) - 对于
x
,y
,z
; 如果x equals y
,y equals z
那么x equals z
(可传递的) - 对于
x
,y
; 如果x equals y
那么y equals x
(对称)
只要你允许inheritance层次结构中的平等,你可以打破2和3.这是由下面的例子显示:
case class Point(x: Int, y: Int) case class ColoredPoint(x: Int, y: Int, c: Color) extends Point(x, y)
那么我们有:
Point(0, 0) equals ColoredPoint(0, 0, RED)
但不是
ColoredPoint(0, 0, RED) equals Point(0, 0)
你可能会争辩说,所有的类层次结构都可能有这个问题,这是真的。 但是,从开发者的angular度来看,案例类是专门用来简化平等的(其他原因),所以让他们不直观的行为将是一个自己的目标的定义!
还有其他的原因。 值得注意的是copy
没有像预期的那样工作,并且与模式匹配器相互作用 。
这不是全部的事实。 这比谎言更糟糕。
正如上文所述,在任何情况下,定义区域的类inheritance者都必须重新定义相等性,因为模式匹配必须完全平等地工作(如果尝试将Point
为ColoredPoint
,则不匹配,因为color
不存在)。
这就使得了解案例级别层次的平等是如何实现的。
case class Point(x: Int, y: Int) case class ColoredPoint(x: Int, y: Int, c: Color) extends Point(x, y) Point(0, 0) equals ColoredPoint(0, 0, RED) // false Point(0, 0) equals ColoredPoint(0, 0, null) // true ColoredPoint(0, 0, RED) equals Point(0, 0) // false ColoredPoint(0, 0, null) equals Point(0, 0) // true
最终甚至可以满足案例类inheritance者(不超越平等)的平等关系的要求。
case class ColoredPoint(x: Int, y: Int, c: String) class RedPoint(x: Int, y: Int) extends ColoredPoint(x, y, "red") class GreenPoint(x: Int, y: Int) extends ColoredPoint(x, y, "green") val colored = ColoredPoint(0, 0, "red") val red1 = new RedPoint(0, 0) val red2 = new RedPoint(0, 0) val green = new GreenPoint(0, 0) red1 equals colored // true red2 equals colored // true red1 equals red2 // true colored equals green // false red1 equals green // false red2 equals green // false def foo(p: GreenPoint) = ???