分享
 
 
 

面向对象方法的困境--正方形不能继承自长方形?

王朝other·作者佚名  2007-06-01
窄屏简体版  字體: |||超大  

面向对象理论诞生之初,由于没有最佳实践的指导,往往导致继承的滥用。一个很著名的例子就是java类库中的堆栈类Stack继承自向量类Vector。

public class Stack extends Vector ...{

public Object push(Object item) ...{

addElement(item);

return item;

}

public synchronized Object pop() ...{

//...

}

}

仅仅是为了重用Vector的管理元素的方法,就让Stack继承自Vector,导致了一个蹩脚的设计。人们后来总结出一条规律:优先使用组合而不是继承,只有当类A确实"is a"类B的时候,才使用继承。Stack不是Vector,所以这个时候应该使用组合。示例代码如下:

public class Stack...{

private Vector vector;

public Object push(Object item) ...{

vector.addElement(item);

return item;

}

//...

}

只有符合"is a"关系时才能使用继承,这条规律是符合我们的直觉的。面向对象技术就是用软件里面的对象模拟现实中的对象。如果狗不是猫,当然不能让狗继承自猫。但是实际的软件开发中,人们很快发现有些情况下即使类A确实"is a"类B,也不能使用继承。最著名的一个例子就是正方形不能继承自长方形了,很多讲面向对象设计的书里都有。这是一个明显违反直觉的例子,示例代码如下:

public class Rectangle ...{

private double width;

private double height;

public Rectangle(double width,double height)...{

this.width=width;this.height=height;

}

public double getHeight() ...{

return height;

}

public void setHeight(double height) ...{

this.height = height;

}

public double getWidth() ...{

return width;

}

public void setWidth(double width) ...{

this.width = width;

}

//...

}

public class Square extends Rectangle...{

public void setHeight(double height) ...{

super.setHeight(height);

super.setWidth(height);

}

public void setWidth(double width) ...{

super.setHeight(width);

super.setWidth(width);

}

//...

}

因为Rectangle类中的setHeight和setWidth方法对Square类不合适,为了保证正方形的长和宽相等,改写了这两个方法。上面的代码初看上去很合理,其实有问题。这个代码的缺陷我就不详细讨论了,很多书都对其做了详细的分析。我只是从理论上指出其不合理之处。根据契约式设计,有下面的原则:

子类的前置条件不能强于父类的前置条件。

子类的后置条件不能弱于父类的后置条件。

子类的类不变式不能弱于父类的类不变式。

这个原则也可以由Liskov替换原则得来。比方说要能够把父类替换成子类,那么父类所接受的任何参数,子类也必须能接受,也就是子类的前置条件不能强于父类的前置条件。

对于长方形类的setHeight方法,其前置条件是height>0,其后置条件是this.height==height&&this.width==old.width。对于正方形类的setHeight方法,其前置条件也是height>0,不强于父类的前置条件。但是其后置条件变成this.height==height&&this.width==height。它违背了父类的后置条件。子类的后置条件不能弱于父类的后置条件的意思是子类必需遵守父类的后置条件,同时还可以加上自己的更强的后置条件。

对于上面这种反常的情况,人们提出了子类型的概念。上面的代码中Square类是Rectangle类的子类(subclass),但是不是子类型(subtype)。因为它违反了Liskov替换原则。这个概念的引入应该说是有很大的混淆性。

那么到底为什么会出现这种反常的情况,正方形就是长方形,使用继承是合情合理的。如果一个设计方法会出现太多的例外情况,那它肯定不是一种好的设计方法。

老师:同学们请看!这是一个正方形,现在我让它的垂直边高度增加,现在成为什么形状了?

学生:报告老师,是长方形。

老师:回答正确。

我们看到在现实中完全可以单独改变正方形的边长,这时改变以后的形状不再是正方形了。通过和现实情况对比,我们受到了启发。那就是正方形和长方形应该是不可变类。当它的边长改变以后,就变成了一个新的长方形。

public class Rectangle ...{

private double width;

private double height;

public Rectangle(double width,double height)...{

this.width=width;this.height=height;

}

public double getHeight() ...{

return height;

}

public double getWidth() ...{

return width;

}

public Rectangle changeHeight(double height) ...{

return new Rectangle(this.width,height);

}

public Rectangle changeWidth(double width) ...{

return new Rectangle(width,this.height);

}

}

public class Square extends Rectangle ...{

public Square(double dege) ...{

super(dege, dege);

}

public Square changeEdge(double edge)...{

return new Square(edge);

}

}

通过这种思路,我们就得到了一个完全和现实对象相吻合的设计。所以说并不是正方形不能继承自长方形。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有