“ Square从Rectangle继承”悖论有特定的名称吗?


18

通过从Rectangle继承的Square类显示了OOP的某些失败,逻辑上Square是Rectangle的特化,因此应该继承自矩形,但是当您尝试更改Square的长度或宽度时,一切都会崩溃。

是否有一个特定的术语来描述这种情况出了什么问题?


2
您能否解释一下“出问题了”的确切含义?我不明白你的意思
蚊蚋

1
假设矩形具有一种允许通过传递长度和宽度来设置大小的虚拟方法,则在正方形上设置不同的长度和宽度可能会返回一个矩形,而在矩形上设置相同的长度和宽度则可能会返回一个正方形。任何需要明确知道平方的代码都可以尝试转换为平方。我看不出怎么回事...

8
这不是悖论。这是问题域建模不正确的情况。继承层次结构不一定要与问题域中事物的层次结构保持一致。这样做的确很不错,但是好的模型中的诀窍是要了解在哪里您需要做的事情与现实世界有所不同。
迈克尔·科恩

1
FWIW:更具体地说,问题是读写接口不匹配。即,您可以将圆作为椭圆的特化来读取,但只能将椭圆作为圆的特化来编写。
Macke

1
@GrandmasterB我要经过“表现出明显矛盾性质的任何人,事物或情况”。矛盾的是,如果正方形具有不同的属性,那么我们必须说“正方形不是某种矩形”,而实际上我们希望正方形是矩形的子类型。可能没有真正的应用程序具有Rectangle和Square类型,这只是说明可能出现在基于类的范式中的某种类型问题的抽象。
维克多

Answers:


27

维基百科仅将其称为圆椭圆问题

圆椭圆问题在软件开发(有时也被称为正方形矩形问题)示出了许多可以在对象建模使用亚型多态性时,会出现缺陷。使用面向对象的编程时,最常遇到这些问题。

这是首字母缩写SOLID中的L ,被称为Liskov替换原理。由于违反该原理而出现此问题。

问题涉及代表圆形和椭圆形(或类似的正方形和矩形)的类之间应该存在哪种子类型或继承关系。更普遍地讲,该问题说明了当基类包含以某种方式使对象变异的方法可能会使派生类中发现的(更强)不变性无效,从而违反Liskov替换原理时可能发生的困难...


1
并且,通过阅读它,维基百科提到了更为学术上的解释,即“违反了利斯科夫替代原则”。谢谢:)
维克多

1
好吧,这只是违规,取决于您如何看待它。就个人而言,所有圈子都是椭圆形。没有违反。如果椭圆的方法变得限制性,就会开始违规。然后,在该特定情况下,圆不能是该特定椭圆合同的子类型。
马克·坎拉斯

6
@MarkCanlas毫无疑问,该问题违反了Liskov替代原则。这可能并不违反其他原则,但是没有人声称这一点。当由于合同中没有包含任何可能被破坏的不变因素而导致问题没有发生时(尽管我无法想象一个有用的模型,如果确实如此),则可能不会违反LSP,但这并不意味着问题(发生时)不是由于违反LSP引起的。

7
@马克·坎拉斯(Mark Canlas):不,恒定的圆是恒定的椭圆,可变的圆不是可变的椭圆。在假定几何常数的情况下,您不能更改椭圆,可以取另一个椭圆
maxim1000 2013年

1
Liskov替代原理的“历史约束/规则”说,当子类型添加新方法时,不允许这些方法以某种方式操纵对象的状态,从而造成对象创建的历史(即一系列状态)不是允许在超类型中使用。例如,您不能使不可变的子类型成为可变的,因为仅当通过超类型的方法进行操作时,状态始终是相同的,而当通过子类型的mutator方法进行操作时,状态则会发生变化。这是超类型所不允许的历史。
约尔格W¯¯米塔格


8

从根本上讲,这比Liskov替代原理更重要,这是类别错误或类别错误

建模行为上下文中,正方形根本不是矩形的类型。

当您意识到这一点时,问题就消失了,因为最初的假设(正方形是矩形的一种)被删除了。

这个答案的问题是,从学校开始,它就被钻进任何从事几何学工作的人,即正方形是矩形的一种。但是,非常重要的一点是要理解这仅在非常特定的上下文中才是正确的(根据几何形状的内角属性对几何形状进行分类)。就行为而言,正方形不是矩形。在错误的上下文中查看一组分类是类别错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.