【设计模式学习】(五)七大原则之里氏替换原则

理论知识


概念

  1. 子类必须完全实现父类的抽象方法,且不可重写父类非抽象方法
  2. 子类可以实现特有方法
  3. 子类可透明访问父类的所有方法

优点

  1. 降低继承带来的耦合性的增加
  2. 子类不重写父类非抽象方法,降低了人为失误导致的代码逻辑错误
  3. 提高代码可读性,使代码更优雅

代码实现


不遵循里氏替换原则

代码
package com.study.liskov;

public class Liskov1 {
    public static void main(String[] args) {
        A a = new A();
        ExtendA ea = new ExtendA();
        System.out.print("输入A: ");
        a.info();
        System.out.print("再输出A: ");
        ea.info();

    }
}

class A{
    public void info() {
        System.out.println("我是A");
    }

    public void baseMethod1(){
        System.out.println("基础方法1");
    }

    public void baseMethod2() {
        System.out.println("基础方法2");
    }
}

class ExtendA extends A{
    public void info() {
        System.out.println("我是extendA");
    }
}


分析

在这里插入图片描述
两个 info() 的目的都是输入A,但由于没有遵循里氏替换原则,开发者在写A的子类extendA时出现失误,将info() 重写为了输出extendA

遵循里氏替换原则

代码
package com.study.liskov;

public class Liskov2 {
    public static void main(String[] args) {
        A1 a = new A1();
        ExtendA1 ea = new ExtendA1();

        System.out.print("输出A: ");
        a.info();
        System.out.print("再输出A: ");
        ea.info();

        System.out.print("ExtendA 中使用 A: ");
        ea.UseA(a);

        System.out.print("参数为BaseA, 传入A: ");
        ea.UseBaseA(a);
    }
}

abstract class BaseA {
    // A类 的基础方法
    public void info() {
        System.out.println("我是A");
    }

    public void baseMethod1() {
        System.out.println("基础方法1");
    }

    public void baseMethod2() {
        System.out.println("基础方法2");
    }

    abstract public void run();
}

class A1 extends BaseA {
    public void uniqueA() {
        System.out.println("A 特有方法");
    }

    @Override
    public void run() {
        System.out.println("A -> running......");
    }
}

class ExtendA1 extends BaseA {
    A1 a = new A1();

    @Override
    public void run() {
        System.out.println("ExtendA -> running......");
    }

    public void UseA(A1 a){
        a.uniqueA();
    }

    public void UseBaseA(BaseA ba) {
        ba.baseMethod1();
    }

}


分析

在这里插入图片描述

  1. 将所有基础方法写入BaseA中,在写A和ExtendA时放置了子类重写父类的问题
  2. 在ExtendA 中使用A, 使用组合的方式
  3. 由于子类能够透明的完全访问父类, 当需要一个BaseA参数时,可以传入一个A

总结思考


如何理解替换?

参数或变量为BaseA时,可以替换成BaseA的任意一个子类: A或ExtendA, 因为子类覆盖了父类的所有抽象方法, 不会出现代码错误,且子类并未覆盖父类的非抽象方法,不会出现逻辑错误

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值