scala 案例类继承有什么问题?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11158929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is *so* wrong with case class inheritance?
提问by Ashkan Kh. Nazary
While looking for something else, quite out of mere coincidence I stumbled upon few comments about how diabolical case class inheritance is. There was this thing called ProductN, wretches and kings, elves and wizards and how some kind of a very desirable property is lost with case classes inheritance. So what is so wrong with case class inheritance ?
在寻找其他东西时,完全出于巧合,我偶然发现了一些关于案例类继承是多么邪恶的评论。有一种东西叫做ProductN, wrtches and kings, elves and Wizards 以及某种非常理想的属性是如何随着案例类继承而丢失的。那么案例类继承有什么问题呢?
回答by oxbow_lakes
One word: equality
一个字:平等
caseclasses come with a supplied implementation of equalsand hashCode. The equivalence relation, known as equalsworks like this (i.e. must have the following properties):
case类带有提供的equals和实现hashCode。等价关系,被称为这样的equals工作(即必须具有以下属性):
- For all
x;x equals xistrue(reflexive) - For
x,y,z; ifx equals yandy equals zthenx equals z(transitive) - For
x,y; ifx equals ytheny equals x(symmetric)
- 对于所有
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(对称)
As soon as you allow for equality within an inheritance hierarchy you can break 2 and 3. this is trivially demonstrated by the following example:
只要您允许继承层次结构中的相等,您就可以打破 2 和 3。以下示例简单地证明了这一点:
case class Point(x: Int, y: Int)
case class ColoredPoint(x: Int, y: Int, c: Color) extends Point(x, y)
Then we have:
然后我们有:
Point(0, 0) equals ColoredPoint(0, 0, RED)
But not
但不是
ColoredPoint(0, 0, RED) equals Point(0, 0)
You might argue that all class hierarchies may have this problem, and this is true. But case classes exist specifically to simplify equality from a developer's perspective (among other reasons), so having them behave non-intuitivelywould be the definition of an own goal!
你可能会争辩说所有的类层次结构都可能有这个问题,这是真的。但是案例类的存在是为了从开发人员的角度(以及其他原因)简化平等,因此让它们的行为不直观将是一个自己的目标的定义!
There were other reasons as well; notably the fact that copydid not work as expectedand interaction with the pattern matcher.
还有其他原因。值得注意的是,copy没有按预期工作以及与模式匹配器交互的事实。
回答by user1303559
That is not overall true. And this is worse than lie.
总体而言并非如此。这比谎言更糟糕。
As mentioned by aepurnietin any case class successor which constricts a definition area must redefine the equality because pattern matching must work exactly as equality (if try to match Pointas ColoredPointthen it will not matched since coloris not exists).
正如aepurniet所提到的,在任何情况下,限制定义区域的类后继者必须重新定义相等性,因为模式匹配必须完全按照相等性工作(如果尝试匹配Point,ColoredPoint那么它将不匹配,因为color不存在)。
That give understanding to how the equality of case class hierarchy could be implemented.
这可以理解如何实现案例类层次结构的相等性。
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
Eventually it is possible to satisfy requirements of the equality relation even for case class successor (without overriding of equality).
最终,即使对于 case class 继承者(不覆盖相等),也可以满足相等关系的要求。
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) = ???

