006六大设计原则-里氏替换原则

1里氏替换原则介绍

在面向对象思想中:继承是很重要的思想

继承的优势:

  • 提高代码的复用性(每个子类有拥有父类的属性和方法)
  • 提高代码的可扩展性

劣势

  • 继承是侵入性的(只要继承,就必须拥有父类的属性和方法)
  • 继承机制很大的增加了耦合性,降低了代码的灵活性
  • 父类的常量、变量和方法被修改时,需要考虑子类的修改

在编程中正确的使用继承思想:就需要使用里氏替换原则

来源:里氏替换原则(Liskov Substitution Principle,LSP)是1988年,麻省理工学院一位姓里的女士提出的

定义:①如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。
(If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.)

②所有引用基类的地方必须能透明地使用其子类的对象。
(Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.)

通俗讲:只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。

白话讲:子类可以扩展父类的功能,但是子类不能修改父类原有的功能,

里氏替换原则规范了继承规则

2模拟场景(违背原则)

随着市场发展有了电子香烟,早期时还没有电子烟

/**
 * @author nzy
 * @create 2021-12-09 17:42
 * 香烟基类
 */
public class Cigarette {
    public void lightCigarette(String name){//用打火机点烟
        System.out.println("点烟的名称是"+name);
    }
    public void smokeing(String name){
        lightCigarette(name);
        System.out.println("抽烟的名称是"+name);
    }
}

public class YuXiCigarette extends Cigarette{//中华
}
public class ZhongHuaCigarette extends Cigarette{//玉溪

}
/**
 * @author nzy
 * @create 2021-12-09 17:47
 * 电子烟
 */
public class ElectronicCigarette extends Cigarette{
}
//调用Client类
public class PersonClient {//人抽烟
    public static void main(String[] args) {
        Cigarette cigarette = new YuXiCigarette();
        cigarette.smokeing("玉溪");
        Cigarette electronicCigarette = new ElectronicCigarette();//调用测试人员并不知道电子烟 是不需要点火的,所以就gg了
        electronicCigarette.smokeing("电子烟");
    }
}

在没有电子烟的时候都是这个过程,现在有电子烟也点烟,所以是有问题的,

3模拟场景(符合原则)

思路:点火是子类特有的方法,所要不要在父类中定义

package com.design.philosophy.lsp.right;

/**
 * @author nzy
 * @create 2021-12-09 17:42
 * 香烟类   创建香烟基类 去掉点火方法,让子类自己去实现
 */
public class Cigarette {
    public void smokeing(String name){
        System.out.println("抽烟的名称是"+name);
    }
}

package com.design.philosophy.lsp.right;

/**
 * @author nzy
 * @create 2021-12-09 18:11
 * 传统香烟需要点火
 */
public class TraditionCigarette extends Cigarette{

    public void lightCigarette(String name){//用打火机点烟
        System.out.println("点烟的名称是"+name);
    }
}


package com.design.philosophy.lsp.right;

/**
 * @author nzy
 * @create 2021-12-09 17:47
 * 电子烟
 */
public class ElectronicCigarette extends Cigarette {
    //不需要写点火方法
    public void userElectricity() {
        System.out.println("抽电子烟用电中");
    }
}

package com.design.philosophy.lsp.right;

/**
 * @author nzy
 * @create 2021-12-09 17:53
 */
public class PersonClient {//人抽烟
    public static void main(String[] args) {
        TraditionCigarette traditionCigarette = new TraditionCigarette();//传统香烟
        traditionCigarette.lightCigarette("中华");
        traditionCigarette.smokeing("中华");

        ElectronicCigarette electronicCigarette = new ElectronicCigarette();
        electronicCigarette.smokeing("电子烟");
    }
}

4总结

代码层面来讲:

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

  在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法

里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖 来解决问题。

里氏替换原则为继承提供了规范

使用里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值