2.里氏替换原则

二、里氏替换原则(lsp)

里氏替换原则的英文缩写是:lsp(谐音梗去记忆~,懂得都懂)

1.概念

任何基类可以出现的地方,子类一定可以出现。通俗理解:子类可以扩展父类的功能,但不能改变父类原有的功能。换句话说,子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法(注意是尽量,而不是必须!!!)

2. 经典案例 -> 正方形不是长方形

我们学过初中数学的都应该知道,正方形是特殊的长方形。假如我们想要开发一款与几何图形的软件相关的系统,我们通常都是让正方形继承长方形。

代码展示:

/**
 * 长方形类
 */
@Data
public class Rectangle {
    /**
     * 长
     */
    private double length;
    /**
     * 宽
     */
    private double width;
}
/**
 * 正方形类
 */
public class Square extends Rectangle {
    @Override
    public void setLength(double length) {
        super.setLength(length);
        super.setWidth(length);
    }

    @Override
    public void setWidth(double width) {
        super.setLength(width);
        super.setWidth(width);
    }
}
public class RectangleDemo {
    public static void main(String[] args) {
        //创建一个长方形
        Rectangle rectangle = new Rectangle();
        rectangle.setLength(20);
        rectangle.setWidth(10);
        resize(rectangle);
        print(rectangle);
        System.out.println("=====================");
        //创建一个正方形
        Square square = new Square();
        square.setLength(20);
        //会发现一直执行扩宽操作
        resize(square);
        print(square);

    }

    /**
     * 扩宽方法,如果宽小于长,则扩宽,知道宽比长大
     */
    private static void resize(Rectangle rectangle) {
        while (rectangle.getWidth() <= rectangle.getLength()) {
            rectangle.setWidth(rectangle.getWidth() + 1);
        }
    }

    /**
     * 打印长和宽
     */
    private static void print(Rectangle rectangle) {
        System.out.println(rectangle.getLength() + " , " + rectangle.getWidth());
    }
}

在这里插入图片描述
我们发现这是一个死循环。

lsp原则要求我们:子类可以扩展父类的功能,但不能改变父类原有的功能。

正方形继承了父类,但是正方形并不适合长方形的resize方法,不满足lsp。

我们可以看到resize这个方法是长方形具备的,但是正方形不具备的,所以这不满足lsp,这不是一个合理的继承关系,当然了,你要非得继承也是可以的,直接在正方形的resize中设置,调用resize就抛异常,直接屏蔽了正方形中的resize方法,但是不合理。

因为这是长方形独有的,所以我们可以抽出去。

正方形和长方形都是四边形。所以我们可以定义一个四边形的接口

修改后的代码:

/**
 * 四边形接口
 */
public interface Quadrilateral {
    /**
     * 获取长
     */
    double getLength();

    /**
     * 获取宽
     */
    double getWidth();
}
/**
 * 长方形类
 */
@Data
public class Rectangle implements Quadrilateral {
    private double length;
    private double width;

    @Override
    public double getLength() {
        return length;
    }

    @Override
    public double getWidth() {
        return width;
    }
}
/**
 * 正方形类
 */
@Data
public class Square implements Quadrilateral {
    private double side;

    @Override
    public double getLength() {
        return side;
    }

    @Override
    public double getWidth() {
        return side;
    }
}

public class Test {
    public static void main(String[] args) {
        Rectangle rectangle = new Rectangle();
        rectangle.setLength(20);
        rectangle.setWidth(10);
        resize(rectangle);
        print(rectangle);
        System.out.println("=====================");
        //Square square = new Square();
        //square.setSide(20);
        //resize(square);
    }

    /**
     * 扩宽方法,此时就是长方形的了,正方形用不了这个接口
     */
    private static void resize(Rectangle rectangle) {
        while (rectangle.getWidth() <= rectangle.getLength()) {
            rectangle.setWidth(rectangle.getWidth() + 1);
        }
    }

    /**
     * 打印长和宽
     */
    private static void print(Rectangle rectangle) {
        System.out.println(rectangle.getLength() + " , " + rectangle.getWidth());
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值