定义:

如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有对象o1都替换为o2时,程序p的行为没有发生变化,那么类型T2是类型T1的子类型.

定义拓展:

一个软件实体如果使用一个父类的话,那一定适用于其子类,所有引用父类的地方必须能透明的使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变.

引申含义:

引申意义:
子类可以扩展父类的功能,但不能改变父类的非抽象方法
子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法.
子类中可以增加自己的特有方法.
当子类的方法重载父类的方法时,方法的前置条件(输入,入参)要比父类方法的输入参数更宽松.
当子类的方法实现父类的方法时(重写、重载或实现抽象方法),方法的后置条件(即方法的输出、返回值)要比父类更严格或相等;

继承破坏:

假设有长方形类Rectangle,子类正方形继承并覆盖方法,编写一个测试类,for循环来改变宽度 当宽度大于等于高度时停止循环.
public class Rectangle {
    private long height;
    private long width;

    public long getHeight() {
        return height;
    }

    public void setHeight(long height) {
        this.height = height;
    }

    public long getWidth() {
        return width;
    }

    public void setWidth(long width) {
        this.width = width;
    }
}

public class Square extends Rectangle {
    private long length;

    public long getLength() {
        return length;
    }

    public void setLength(long length) {
        this.length = length;
    }

    @Override
    public long getHeight() {
        return getLength();
    }

    @Override
    public void setHeight(long height) {
        setLength(height);
    }

    @Override
    public long getWidth() {
        return getLength();
    }

    @Override
    public void setWidth(long width) {
        setLength(width);
    }
}

public class SimpleTest {

    public static void resize(Rectangle rectangle){
        while (rectangle.getWidth() >= rectangle.getHeight()){
            rectangle.setHeight(rectangle.getHeight() + 1);
            System.out.println("Width:" +rectangle.getWidth() +",Height:" + rectangle.getHeight());
        }
        System.out.println("Resize End,Width:" +rectangle.getWidth() +",Height:" + rectangle.getHeight());
    }



    public static void main(String[] args) {
        Square square = new Square();
        square.setLength(10);
        resize(square);
    }
测试结果长方形调用resize 一切正常 ,但是子类调用resize就会出现死循环,不符合李氏替换原则;
修改后的代码:
定义一个四边形接口QuadRangle,长方形和正方形分别去实现:
public interface QuadRangle {
    long getWidth();
    long getHeight();
}

public class Rectangle implements QuadRangle {
    private long height;
    private long width;

    public long getHeight() {
        return height;
    }

    public void setHeight(long height) {
        this.height = height;
    }

    public long getWidth() {
        return width;
    }

    public void setWidth(long width) {
        this.width = width;
    }
}

public class Square implements QuadRangle {
    private long length;

    public long getLength() {
        return length;
    }

    public void setLength(long length) {
        this.length = length;
    }

    public long getWidth() {
        return length;
    }

    public long getHeight() {
        return length;
    }
}

public class IspTest {

    public static void resize(QuadRangle quadRangle){
        while (quadRangle.getWidth() >= quadRangle.getHeight()){
            quadRangle.setHeight(quadRangle.getHeight() + 1);
            System.out.println("Width:" +quadRangle.getWidth() +",Height:" + quadRangle.getHeight());
        }
        System.out.println("Resize End,Width:" +quadRangle.getWidth() +",Height:" + quadRangle.getHeight());
    }
因为QuadRangle只有边长,没有高宽的概念,当测试类传入QuadRangle时setHeight方法便会报错,这样就能杜绝继承泛滥的问题.

入参和返回参数:

子类重载父类的方法入参要更宽松:
public class Base {
    public void method(HashMap map){
        System.out.println("父类执行");
    }
}
public class Child extends Base {
    @Override
    public void method(HashMap map) {
        System.out.println("执行子类HashMap入参方法");
    }
    public void method(Map map){
        System.out.println("执行子类Map入参方法");
    }

}

public class MethodParamTest {
    public static void main(String[] args) {
        Base child = new Child();
        HashMap hashMap = new HashMap();
        child.method(hashMap);
    }
}

上面代码Base child = new Child(); Child child = new Child();运行一切正常.

如果子类重写入参小于父类:
public class Base {
    public void method(Map map){
        System.out.println("父类执行");
    }
}

public class Child extends Base {
/*   @Override
    public void method(HashMap map) {
        System.out.println("执行子类HashMap入参方法");
    }*/

    public void method(HashMap map){
        System.out.println("执行子类Map入参方法");
    }
}

public class MethodParamTest {
    public static void main(String[] args) {
        Base child = new Child();
        HashMap hashMap = new HashMap();
        child.method(hashMap);
    }
}

测试发现改变了执行结果.

子类的方法实现父类的方法时(重写、重载或实现抽象方法),方法的后置条件(即方法的输出、返回值)要比父类更严格或相等:
public abstract class Base {
    public abstract Map method();
}

public class Child extends Base {
    @Override
    public HashMap method() {
        HashMap hashMap = new HashMap();
        System.out.println("执行子类的method");
        hashMap.put("msg","子类method");
        return hashMap;
    }
}

public class MethodReturnTest {
    public static void main(String[] args) {
        Base child = new Child();
        System.out.println(child.method());
    }
}

如果子类的返回条件更宽松,Ide都会直接报错.