栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java七大设计原则(3/7)——里氏替换原则

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java七大设计原则(3/7)——里氏替换原则


定义

里氏代换原则,任何基类可以使用的地方,子类一定可以使用。但反过来不一定成立,子类出现的地方,基类不一定能使用。即子类可以拓展父类,但不能更改父类原有的功能。


概述
  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  • 子类可以增加自己特有的方法。
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类方法的输入参数更宽松。
  • 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类更严格或与父类一样

后两句可以概括为:接受的参数(类型)范围比父类大,返回的参数(类型)范围比父类小


作用
  • 里氏替换原则是实现开闭原则的重要方式之一;
  • 解决了继承中重写父类造成的可复用性变差的问题;
  • 是动作正确性的保证,即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性;
  • 加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性、可扩展性,降低需求变更时引入的风险。

代码实现

假设有一个燕子和一个企鹅,它们都是鸟,但是企鹅不会飞。

现在要计算它们移动一定距离所需的时间。

不使用里氏替换原则

定义Bird类

public class Bird {
    double flySpeed;

    public void setFlySpeed(double speed) {
        this.flySpeed = speed;
    }

    public double getFlyTime(double distance){`在这里插入代码片`
        return distance/flySpeed;
    }
}

定义Swallow类

public class Swallow extends Bird{

}

定义Penguin类

public class Penguin extends Bird {
    @Override
    public void setFlySpeed(double speed) {
        this.flySpeed = 0;
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        Bird swallow = new Swallow();
        Bird penguin = new Penguin();
        swallow.setFlySpeed(180);
        penguin.setFlySpeed(180);
        System.out.println("飞行距离为300公里");
        System.out.println("swallow将飞行 "+swallow.getFlyTime(300)+" 小时");
        System.out.println("penguin将飞行 "+penguin.getFlyTime(300)+" 小时");
    }
}

结果为
很明显,这不是想要的结果,因为企鹅不会飞,它的飞行速度为0,所以结果才会显示 Infinity。

再来看看使用里氏替换原则是怎样的


使用里氏替换原则

这里把Bird类和Penguin类进一步抽象,定义一个Animal类。

Animal类有一个 runSpeed 属性,这很合理,毕竟鸟也能 run 嘛。

public class Animal {
    double runSpeed;

    public void setRunSpeed(double runSpeed) {
        this.runSpeed = runSpeed;
    }

    public double getRunTime(double distance) {
        return distance/runSpeed;
    }
}

再定义Brid类,Bird类继承Animal类,Bird类有自己的 flySpeed 属性

public class Bird extends Animal{
    double flySpeed;

    public void setFlySpeed(double flySpeed) {
        this.flySpeed = flySpeed;
    }

    public double getFlyTime(double distance) {
        return distance/flySpeed;
    }
}

再定义Swallow类与Penguin类,分别继承Bird类和Animal类。

这里Swallow就有 runSpeed 属性和 flySpeed 属性了,而因为Penguin不能飞,所以它只有 runSpeed 属性

public class Swallow extends Bird{
}
public class Penguin extends Animal{
}

测试

public class Test {
    public static void main(String[] args) {
        Bird swallow = new Swallow();
        Animal penguin = new Penguin();
        swallow.setFlySpeed(120);
        penguin.setRunSpeed(20);
        System.out.println("如果移动300公里:");
        System.out.println("swallow将移动:" + swallow.getFlyTime(300) + "小时");
        System.out.println("penguin将移动:" + penguin.getRunTime(300) + "小时");
    }
}

输出结果

这里才是符合预期的地方。

这个例子展示了里氏替换原则作用之一——保证动作正确性,其实里氏替换原则还能做更多事情。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/924557.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号