case caseinheritance的* so *错误是什么?

在寻找别的东西的时候,很偶然的,我偶然发现了一些关于恶意案例类inheritance的评论。 有这样的东西,叫做ProductN ,可怜的人,国王,精灵和巫师,以及某种非常理想的财产如何失去案例类inheritance。 那么case类inheritance有什么问题呢?

一个字: 平等

case类提供了equalshashCode的提供的实现。 等价关系,称为equals这样(即必须具有以下属性):

  1. 对于所有的x ; x equals xtrue (反身)
  2. 对于xyz ; 如果x equals yy equals z那么x equals z (可传递的)
  3. 对于xy ; 如果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者都必须重新定义相等性,因为模式匹配必须完全平等地工作(如果尝试将PointColoredPoint ,则不匹配,因为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) = ???