面向对象的设计原则四 - 里氏代换原则

动机

当我们设计程序模块时,我们会创建一些类层次结构,然后我们通过扩展一些类来创建它们的子类。

我们必须确保子类只是扩展而没有替换父类的功能,否则当我们在已有程序模块中使用它们时将会产生不可预料的结果。

 

里氏代换原则表明当一个程序模块使用基类时,基类的引用可以被子类替换而不影响模块的功能。

 

里氏代换原则

基类完全能够被子类替代而不影响模块的功能。

 

实例

 

对于多态来说里氏代换原则好像是很显然的事情,例如:

Java代码 复制代码  收藏代码
  1. public void drawShape(Shape s) {   
  2. // Code here.   
  3. }  
public void drawShape(Shape s) {
// Code here.
}

 

对于Shape的任何子类来说,drawShape方法都应该能很好的工作。我们必须小心的实现子类以免无意中违反了里氏代换原则,如果一个函数不满足里氏代换原则,那么它可能必须显式地引用子类对象,这样的函数同样违反了开闭原则,因为当添加新的子类时,必须修改它。

考虑下面的矩形类:  

现在,如果有个正方形呢?显然正方形是一个矩形,所以我们应该让正方形继承矩形类,是这样吗?我们看一下!

 

注意:

  • 正方形不需要同时具有宽和高属性,但是它还是从矩形继承了这些属性。所以,每个正方形都浪费了一点空间,但这不是我们关注的主要问题。
  • 继承而来的setWidth()和setHeight()方法实际上对于正方形是不合适的,因为正方形的宽和高是相等的。所以我们需要重写setWidth()和setHeight()方法,这可能暗示着在这儿并不适合使用继承。

下面是Square类:  

一切看上去都很好,但是注意下面的代码:  

测试程序输出:  

看起来我们违反了里氏代换原则,问题在哪儿?testLSP()方法合理的假设当一个矩形的宽改变时,它的高度不变。当传递一个正方形对象时,该方法却违反了里氏代换原则。从数学上看,正方形是一个矩形,但是一个正方形对象却不是矩形对象,因为一个正方形对象的行为和一个矩形对象的行为不一致。从行为上来说,正方形不是矩形!里氏代换原则清晰的说明,IS-A关系是对于所有的行为来说的,为了遵循里氏代换原则,子类的行为必须和客户端使用的基类的行为一致。

子类不能比基类具有更多的约束,因为必须在任何可以使用基类的地方使用子类,如果子类比基类有更多的约束,那么就会出现基类可用,但却违反了子类约束的情况。

 

总结

里氏代换原则是对开闭原则的扩展,它表明我们在创建基类的新的子类时,不应该改变基类的行为。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值