@H_
502_0@ 肯定有不少人跟我刚看到这项原则的时候一样,对这个原则的名字充满疑惑。其实原因就是这项原则最早是在1988年,由麻省理工学院的一位姓里的女士(Barbara Liskov)提出来的。
@H_
502_0@
定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
@H_
502_0@
定义2:所有引用基类的地方必须能透明地使用其子类的对象。
@H_
502_0@
问题由来:有一
功能P1,由类A完成。现需要将
功能P1进行扩展,扩展后的
功能为P,其中P由原有
功能P1与新
功能P2组成。新
功能P由类A的子类B来完成,则子类B在完成新
功能P2的同时,有可能会导致原有
功能P1发生故障。
@H_
502_0@
解决方案:当使用继承时,遵循里氏替换原则。类B继承类A时,除
添加新的
方法完成新增
功能P2外,尽量不要重写
父类A的
方法,也尽量不要重载
父类A的
方法。
@H_
502_0@ 继承包含这样一层含义:
父类中凡是已经实现好的
方法(相对于抽象
方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象
方法任意
修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。
@H_
502_0@ 继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,
增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要
修改时,必须考虑到所有的子类,并且
父类修改后,所有涉及到子类的
功能都有可能会产生故障。
@H_
502_0@ 举例说明继承的风险,我们需要完成一个两数相减的
功能,由类A来负责。
- classA{
- publicintfunc1(inta,intb){
- returna-b;
- }
- }
-
- classClient{
- staticvoidmain(String[]args){
- Aa=newA();
- System.out.println("100-50="+a.func1(100,50));
- System.out.println("100-80="+a.func1(80));
- }
@H_
502_0@
运行结果:
100-50=50
100-80=20
@H_
502_0@ 后来,我们需要
增加一个新的
功能:完成两数相加,然后再与100求和,由类B来负责。即类B需要完成两个
功能:
@H_
502_0@ 由于类A已经实现了第一个
功能,所以类B继承类A后,只需要再完成第二个
功能就可以了,
代码如下: