我正在开发一个小型绘图应用程序,可以拖放一些“复杂”形式的库。
当我从一群其他人那里扩展出大量的物体层次时,我总是怀疑。特别是,我并不总是知道什么是最佳实践,为纯代码压缩目的扩展对象,或者仅在语义上有意义时扩展对象。
这里有一个简单的例子。我有一个带有一个属性的方形对象:edge。然后是一个矩形和许多其他形状。矩形是否应该从正方形延伸,因为它只是添加参数?或者我应该反过来因为square是数学中矩形的特化?两种方式似乎都存在问题。
答案 0 :(得分:3)
请注意,扩展意味着是关系。在你的情况下,制作矩形扩展正方形就像是说“矩形是正方形”(就几何而言,它不是必然的)。因此,对于我来说,制作正方形扩展矩形更有意义,因为“正方形是矩形”更正确。
一般来说,如果你计划包含“许多其他形状”,似乎在方形或矩形中具有“边缘”属性是很奇怪的。我会建议一个 Polygon 类,它包含一组边,然后是矩形或四边形类,它扩展了Polygon,然后可能是 Square 或 Regular四边形类扩展了它。
答案 1 :(得分:2)
乔纳森的答案是最正确的,但考虑只是让一切都变成一个简单的Shape : Polygon
关系。从矩形中获取Square有什么收获(如果你确实甚至需要一个Square)?如果没有什么可以获得的,那么就不要这样做。这应该是OOP的第一原则。巨大的类层次结构难以维护,因此您的第一步是确定是否需要这样做。
此外,您似乎对继承的含义感到困惑。继承不仅仅是拥有比父类更多参数或方法的质量,而是根据域规则成为该类的子集的质量。大多数时候会有其他属性,但并非总是如此。就像乔纳森所说,一个矩形在现实生活中不是一个正方形,因此它不能从Square
类派生出来。
在您的矩形和方形示例中,您似乎坚持认为Square
只有一个参数edge
,但是它使width
和length
同时保持不变参数,每个都相等?在这种情况下,您可以声明正方形是一个矩形,强制执行相等长度和宽度的规则。这种方式很简单,并且不违反OO。
答案 2 :(得分:0)
即使是非常简单的例子,将继承视为“依存”关系也会失效。
正如您在问题中指出的那样,正方形看起来像是一种特殊的矩形。这个事实表明矩形应该从正方形继承。但是,请考虑以下代码: -
foo( Rectangle r )
{
r.setWidth( 5 );
r.setHeight( 10 );
print( r.getWidth() );
}
根据您是否传入Rectangle
或Square
的实例,答案会有所不同。 Square
无法取代Rectangle
。从某种意义上说,square不是一个矩形。向子类添加约束会破坏Liskov Substitution Principle。当子类具有父类中不存在的额外约束时,继承不适合。
所以也许Rectangle
延伸Square
?它就像一个具有额外特殊功能的正方形myWidth
可能与myHeight
不同?
继承的成员变量myEdgeLength
会变成什么?这是多余的,任何使用它可能是一个错误。
程序员出现并向getPerimeter()
添加Square
方法。因此,Rectangle
继承了这一点。它会给出错误的答案。继承没有帮助。
我建议继承在这里根本没用。 Square
应该在内部使用矩形。在构造Square
时,它会创建自己的Rectangle
内部表示,并将其放在成员变量中。
当setEdgeLength
被调用时,它会调用myRectangle.setWidth( x )
和myRectangle.setHeigth( x )
。调用getArea()时,它会委托给myRectangle.getArea
。
也可以委派许多其他功能。例如:containsPoint,getPerimiter,重叠等
令人遗憾的是,语言需要样板来进行委派。