这是一个无聊的学术OOP问题,但它不是家庭作业。我从一位新手程序员那里得到了一个关于OOP的愚蠢教科书例子的问题。
想象一下,你正在设计一个Square类和一个Cube类,它应该继承哪个?
我看到了一段感情,但它是什么,我真的看不到!
你能不能给我一个关于OOP的逻辑论证。
答案 0 :(得分:22)
既不!由于正方形不是立方体,而立方体不是正方形,因此它们都不应该从另一个立方体继承。 Square可以从多边形继承,而cube可以从多面体继承,但这两者本身是互斥的。
答案 1 :(得分:14)
没有继承权。 继承是一种“is-a”关系(好吧,有时甚至不是“is-a”关系,如下面的链接所示)。立方体不是正方形,正方形不是立方体。
你将如何构建,这取决于你的模型。你可以选择像立方体这样的东西有6个正方形(一个立方体不是,它有6个正方形;一个构图),或者一个立方体有一个侧面尺寸,就像方形一样。但是一旦没有“是-a”,继承就会成为危险区域......
此外,在继承中,对基类有效的所有内容必须对派生的有效。这是Square extends Rectangle问题。例如:
假设Cube继承Square:如果你的Square有一个方法changeArea(double area)和getSide(),那么Cube应该是可能的。但事实并非如此,因为立方体的面积是正方形面积的6倍(它有6个正方形)。
假设Square继承Cube:如果你的Cube有一个setVolume(双卷)方法,一旦没有音量,你的方块就会被打破
最后,如果要使用继承,可以创建 GeometryObjectWithEqualSides 对象,然后两者都可以继承它。 :)
答案 2 :(得分:6)
无论采用哪种方式都会违反Liskov Substitution Principle。
答案 3 :(得分:1)
都从超立方体继承
答案 4 :(得分:1)
struct Square // Rectangle actually
{
Square( int dx, int dy ) : dx(dx), dy(dy) {};
int dx;
int dy;
int floor_area() { return dx*dy; };
};
struct Cube : Square // Cuboid actually
{
Cube( int dx, int dy, int dz ) : Square(dx, dy), dz(dz) {};
int dz;
int cube_area() { return floor_area()*2+dx*dz*2+dy*dz*2; };
};
这里似乎没有违反Liskov substitution principle。
答案 5 :(得分:1)
正方形和立方体可以被认为是同一类“超立方体”的两个实例,它们也包含点(0维),线段(1维)以及其他类别。尺寸的数量和一边的长度足以定义超立方体的特定实例(当然,您可以添加一个n维原点和方向)。
超立方体可以提供函数/方法,返回该特定实例的顶点,边,面等数量的值。
有关详细信息,请参阅维基百科上的Hypercube。
答案 6 :(得分:0)
也不应该继承另一个。一个是二维形状,另一个是三维物体。两者之间确实没有足够的相似性来证明继承的合理性。
现在你可以设想制作一个方块的组成,如果你需要为每一方分别设置一个对象;)
答案 7 :(得分:0)
这里的大多数评论都正确地说它们都不应该从另一个继承。在大多数情况下都是如此。但我认为有更通用的答案: 这取决于您对他们的期望。 你期待Square做什么? Cube也做了吗?可能是另一种方式 - 无论何时使用Cube,你都可以使用Square吗? 根据常识,我认为两个陈述“Cube完成Square所做的一切”和“Square做Cube所做的一切”都是错误的,因此它们都不应该从另一个继承。但是,由您来决定其结构和行为,因为您可以定义您的程序的功能及其组成部分。
很可能“立方体包含6个正方形”就是你所看到的关系。