里氏替换原则(Liskov Substitution Principle,简称LSP)是面向对象设计中的一个原则,它规定如果一个类型是另一个类型的子类型,那么应该可以替换掉父类型的对象而不影响程序的正确性。简而言之,子类型必须能够替换其基类型。

反例:

class Rectangle {
    protected int width;
    protected int height;

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

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

    public int calculateArea() {
        return width * height;
    }
}

class Square extends Rectangle {
    @Override
    public void setWidth(int width) {
        super.setWidth(width);
        super.setHeight(width);
    }

    @Override
    public void setHeight(int height) {
        super.setHeight(height);
        super.setWidth(height);
    }
}

在这个例子中,Square 类继承自 Rectangle 类,但是为了满足正方形的特性,覆写了父类的 setWidth 和 setHeight 方法。这样的设计违反了里氏替换原则,因为使用基类 Rectangle 的代码在替换成子类 Square 后可能导致错误。例如:

Rectangle rectangle = new Square();
rectangle.setWidth(5);
rectangle.setHeight(10);
int area = rectangle.calculateArea(); // 预期结果是50,但实际结果是100

在这个例子中,虽然使用 Rectangle 类型的引用指向了 Square 类的对象,但由于 Square 类在设置宽度和高度时有特殊处理,导致最终的计算面积结果不符合预期。

正例:

class Shape {
    // 定义通用的形状类
}

class Rectangle extends Shape {
    protected int width;
    protected int height;

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

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

    public int calculateArea() {
        return width * height;
    }
}

class Square extends Shape {
    protected int side;

    public void setSide(int side) {
        this.side = side;
    }

    public int calculateArea() {
        return side * side;
    }
}

在正例中,Rectangle 和 Square 都继承自通用的形状类 Shape,并且都提供了各自计算面积的方法。这样,可以保证在使用基类 Shape 的代码中,可以用任何子类对象替代而不引起错误。这符合里氏替换原则,子类可以替代父类而不产生意外行为。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注