设计模式–七大原则--里斯替换原则

里斯替换原则

基本介绍

Liskov Subsitution Principle (LSP) 里氏替换原则

Functions that use pointers of references to base classes must be able to use object of derived classes without knowing it

子类对象(object of subtype/derived class)能够替换程序(program)中父类对象(object of base/parent class)出现的任何方,并且保证原来程序的逻辑行为(behavior)不变及正确性不被破坏。

如何理解"里斯替换原则"?

里斯替换原则需要注意:

  • 子类对象能够替换程序中父类对象
  • 替换后不能改变父类的任何功能(例如:异常种类)

哪些代码明显违背了LSP?

1. 子类违背父类声明要实现的功能
2. 子类违背父类对输入、输出、异常的约定
3. 父类违背注释中所罗列的任何特殊说明

里氏替换原则与多态的关系

里斯替换和多态类似但不相同,两者的关注点不同

  • 多态是面向对象的一大特性,也是面向对象编程语言的的一种语法,它是一种代码实现的思路。
  • 里氏替换是一种设计原则,不改变所有程序的逻辑以及不破坏原有程序的正确性

个人理解

  • 多态是一种行为,不同的人对于这种行为可以做出不同的反应,这是面向对象编程语言所具备的
  • 里氏替换可以理解为有一个球员,该球员有两个替补,在该球员不能上场的时候,两个替补可以直接上场进行比赛(不强调能不能进球)

应用示例

// A类
class A {
    // 返回两个数的差
    public int func1(int num1, int num2) {
        return num1 - num2;
    }
}

// B类继承了A
// 增加了一个新功能:完成两个数相加,然后和9求和
class B extends A {
    //这里,重写了A类的方法, 可能是无意识
    public int func1(int a, int b) {
        return a + b;
    }

    public int func2(int a, int b) {
        return func1(a, b) + 9;
    }
}

public class Liskov {

    public static void main(String[] args) {
        A a = new A();
        System.out.println("11-3=" + a.func1(11, 3));
        System.out.println("1-8=" + a.func1(1, 8));

        System.out.println("-----------------------");
        B b = new B();
        System.out.println("11-3=" + b.func1(11, 3));//这里本意是求出11-3
        System.out.println("1-8=" + b.func1(1, 8));// 1-8
        System.out.println("11+3+9=" + b.func2(11, 3));
    }
}

分析: 上面的B类明显不能用A类进行替换

//创建一个更加基础的基类
class Base {
    //把更加基础的方法和成员写到Base类
}

// A类
class A extends Base {
    // 返回两个数的差
    public int func1(int num1, int num2) {
        return num1 - num2;
    }
}

// B类继承了A
// 增加了一个新功能:完成两个数相加,然后和9求和
class B extends Base {
    //如果B需要使用A类的方法,使用组合关系
    private A a = new A();

    //这里,重写了A类的方法, 可能是无意识
    public int func1(int a, int b) {
        return a + b;
    }

    public int func2(int a, int b) {
        return func1(a, b) + 9;
    }

    //我们仍然想使用A的方法
    public int func3(int a, int b) {
        return this.a.func1(a, b);
    }
}

public class Liskov {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        A a = new A();
        System.out.println("11-3=" + a.func1(11, 3));
        System.out.println("1-8=" + a.func1(1, 8));

        System.out.println("-----------------------");
        B b = new B();
        //因为B类不再继承A类,因此调用者,不会再func1是求减法
        //调用完成的功能就会很明确
        System.out.println("11+3=" + b.func1(11, 3));//这里本意是求出11+3
        System.out.println("1+8=" + b.func1(1, 8));// 1+8
        System.out.println("11+3+9=" + b.func2(11, 3));


        //使用组合仍然可以使用到A类相关方法
        System.out.println("11-3=" + b.func3(11, 3));// 这里本意是求出11-3


    }

}

分析:提取一个Base类,把A和B公共方法放到Base基类中

注:本文是根据尚硅谷和极客学院的课程整理的学习笔记,如要深入理解,请收看老师的原版视频。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值