一.由来。1988年由由麻省理工学院的以为姓里的女士提出的。
二.解决什么实际问题呢?子类继承父类时,重写父类方法,可能会破坏整个继承体系。
来看看实例:
package com.yrz.liskovsubstitution;
public class LiskovSubstitution {
public static void main(String[] args) {
A a = new A();
System.out.println("11-3=" + a.func1(11, 3));
System.out.println("1-8=" + a.func1(1, 8));
System.out.println("-----------------------");
B b = new B();
System.out.println("11-3=" + b.func1(11, 3));
System.out.println("1-8=" + b.func1(1, 8));
System.out.println("11+3+9=" + b.func2(11, 3));
}
}
class A {
public int func1(int num1, int num2) {
return num1 - num2;
}
}
class B extends A {
public int func1(int a, int b) {
return a + b;
}
public int func2(int a, int b) {
return func1(a, b) + 9;
}
}
运行结果:
11-3=8
1-8=-7
-----------------------
11-3=14
1-8=9
11+3+9=23
分析:可以看到 类B中 11-3=14,这是因为类B重写了类A的方法。
怎么解决呢?
将两个类都要使用的方法进行抽象。
public class LiskovSubstitutionImp {
public static void main(String[] args) {
AImp a = new AImp();
System.out.println("11-3=" + a.func1(11, 3));
System.out.println("1-8=" + a.func1(1, 8));
System.out.println("-----------------------");
BImp b = new BImp();
// 因为B类不再继承A类,因此调用者,不会再func1是求减法
// 调用完成的功能就会很明确
System.out.println("11+3=" + b.func1(11, 3));// 这里本意是求出11+3
System.out.println("1+8=" + b.func1(1, 8));// 1+8
System.out.println("11+3+9=" + b.func2(11, 3));
// 使用组合仍然可以使用到A类相关方法
System.out.println("11-3=" + b.func3(11, 3));// 这里本意是求出11-3
}
}
class Base {
// 更抽象的基类
}
class AImp extends Base {
public int func1(int num1, int num2) {
return num1 - num2;
}
}
class BImp extends Base {
AImp aImp = new AImp();
// 重写AImp减法
public int func1(int a, int b) {
return a + b;
}
public int func2(int a, int b) {
return func1(a, b) + 9;
}
// 仍然使用AImp的func1方法
public int func3(int a, int b) {
return this.aImp.func1(a, b);
}
}
运行结果:
11-3=8
1-8=-7
-----------------------
11+3=14
1+8=9
11+3+9=23
11-3=8
分析:解决方式是采用抽象出更基础的父类,使用组合的方式实现类A的方法在类B中调用。
总结:在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法。
里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可
以通过聚合,组合,依赖 来解决问题。.