2012-07-12 33 views
2

你可以有一个超类Shape,Square和Rectangle是两个子类,但是你可以有Square子类Rectangle,因为Square是一个特殊的矩形,四边相等。Square和Rectangle可以继承Shape,但可以Square子类Rectangle?

我试图使用这样一个原则来检查,即每当使用超类时,它应该能够被其子类替换,但是如果使用子类,则可能无法被其超类替换类。看起来很好,但我总是觉得Square不能成为Rectangle的孩子出于某种原因?任何人都能给我一些亮光吗?

回答

3

您指的是Liskov Substition Principle

可替代性是面向对象编程的一个原则。它指出,在一个计算机程序中,如果S是T的一个子类型,那么类型T的对象可以用类型S的对象代替(即,类型S的对象可以代替类型T的对象),而不改变任何该程序的理想属性(正确性,执行的任务等)。

具体到你的问题:

违反LSP是正方形类从一个矩形类派生,假设二者的宽度和高度存在获取和设置方法的典型例子。 Square类始终假设宽度与高度相等。如果在需要Rectangle的上下文中使用Square对象,则可能会发生意外的行为,因为Square的尺寸不能单独修改(或者不应该)。这个问题不容易修正:如果我们可以在Square类中修改setter方法,以便它们保留Square不变量(即保持尺寸相等),那么这些方法将削弱(违反)Rectangle设置器的后置条件,说明尺寸可以独立修改。违反LSP,像这样,在实践中可能会也可能不会成为问题,这取决于使用违反LSP的类的代码实际预期的后置条件或不变量。可变性是一个关键问题。如果Square和Rectangle只有getter方法(即它们是不可变对象),则不会发生违反LSP的情况。

用简单的英语,则无法使用其中一个Rectangle预期,因为广场有行为的Rectangle没有一个广场。如果有人试图使用他们认为应该是Rectangle的实例,但它确实是Square的一个实例,他们可能会设置宽度并且会惊讶高度会自动更改(意外的副作用)。

+0

只是作为一个nitpicker:一个不可变的矩形可能是一个方形的子类... – 2012-07-12 05:14:07

+0

无论如何有一个方形的背后有什么想法?如果所有方面都相同,它就变成了一个正方形。所以作为一个正方形,更像是一种财产,而不是一种行为。如果将其视为行为,则必须分别处理缩比三角形,圆/椭圆等。如果仅仅实施一种辅助方法,它会更有意义吗? 'setSide(...)'是标准的,'setSides(...)'将同时设置所有的(并且以这种方式创建一个正方形)。在我看来,在这种情况下,我们从“结果”中获取属性并将其转换为功能。 – Katai 2012-07-12 07:20:16

+0

@Anders:的确如此:-)这是在维基百科报价的最后两句中说明的。 – 2012-07-14 17:02:52