精华内容
下载资源
问答
  • 主要介绍了PHP面向对象五大原则之里氏替换原则(LSP),较为详细的分析了里氏替换原则(LSP)的概念、原理并结合实例形式分析了php里氏替换原则(LSP)的简单使用方法,需要的朋友可以参考下
  • 里氏替换原则Demo

    2015-11-28 16:31:20
    http://blog.csdn.net/xingjiarong/article/details/50081857
  • 里氏替换原则

    2021-01-28 20:34:06
    一 点睛 里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则:任何基类可以出现的地方,子类...下面是一个违背里氏替换原则的经典例子。 二 反例——正方形是长方形 1 分析 在数学领域里,正方形毫无疑问是长

    一 点睛

    里氏代换原则是面向对象设计的基本原则之一。
    里氏代换原则:任何基类可以出现的地方,子类一定可以出现。通俗理解:子类可以扩展父类的功能,但不能改变父类原有的功能。换句话说,子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
    如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。
    下面是一个违背里氏替换原则的经典例子。

    二 反例——正方形是长方形

    1 分析

    在数学领域里,正方形毫无疑问是长方形,它是一个长宽相等的长方形。所以,我们开发一个与几何图形相关的软件系统,就可以顺理成章的让正方形继承自长方形。
    在这里插入图片描述

    2 代码

    长方形类(Rectangle):

    public class Rectangle {
        private double length;
        private double width;
    
        public double getLength() {
            return length;
        }
    
        public void setLength(double length) {
            this.length = length;
        }
    
        public double getWidth() {
            return width;
        }
    
        public void setWidth(double width) {
            this.width = width;
        }
    }
    

    正方形类(Square):

    由于正方形的长和宽相同,所以在方法setLength和setWidth中,对长度和宽度都需要赋相同值。

    public class Square extends Rectangle {
        // 重写父类方法,它会带来恶果 
        public void setWidth(double width) {
            super.setLength(width);
            super.setWidth(width);
        }
        // 重写父类方法,它会带来恶果 
        public void setLength(double length) {
            super.setLength(length);
            super.setWidth(length);
        }
    }
    

    类RectangleDemo:
    它是我们的软件系统中的一个组件,它有一个resize方法依赖基类Rectangle,resize方法是RectandleDemo类中的一个方法,用来实现宽度逐渐增长的效果。

    public class RectangleDemo {
        
        public static void resize(Rectangle rectangle) {
            while (rectangle.getWidth() <= rectangle.getLength()) {
                rectangle.setWidth(rectangle.getWidth() + 1);
            }
        }
    
        //打印长方形的长和宽
        public static void printLengthAndWidth(Rectangle rectangle) {
            System.out.println(rectangle.getLength());
            System.out.println(rectangle.getWidth());
        }
    
        public static void main(String[] args) {
            Rectangle rectangle = new Rectangle();
            rectangle.setLength(20);
            rectangle.setWidth(10);
            resize(rectangle);
            printLengthAndWidth(rectangle);
    
            System.out.println("============");
    
            Rectangle rectangle1 = new Square();
            rectangle1.setLength(10);
            resize(rectangle1);
            printLengthAndWidth(rectangle1);
        }
    }
    

    运行一下这段代码。
    假如我们把一个普通长方形作为参数传入resize方法,就会看到长方形宽度逐渐增长的效果,当宽度大于长度,代码就会停止,这种行为的结果符合我们的预期。
    假如我们再把一个正方形作为参数传入resize方法后,就会看到正方形的宽度和长度都在不断增长,代码会一直运行下去,直至系统产生溢出错误。
    所以,普通的长方形是适合这段代码的,正方形不适合。

    三 正例—— 正方形不是长方形

    1 分析

    从上面的反例中我们可以得出这样的结论:在resize方法中,Rectangle类型的参数是不能被Square类型的参数所代替,如果进行了替换就得不到预期结果。因此,Square类和Rectangle类之间的继承关系违反了里氏代换原则,它们之间的继承关系不成立,正方形并不是长方形。

    如何改进呢?此时我们需要重新设计他们之间的关系。抽象出来一个四边形接口(Quadrilateral),让Rectangle类和Square类实现Quadrilateral接口
    在这里插入图片描述

    2 代码

    Quadrilateral

    public interface Quadrilateral {
        // 获取长
        double getLength();
        // 获取宽
        double getWidth();
    }
    

    Rectangle

    public class Rectangle implements Quadrilateral {
        private double length;
        private double width;
    
        public void setLength(double length) {
            this.length = length;
        }
    
        public void setWidth(double width) {
            this.width = width;
        }
    
        public double getLength() {
            return length;
        }
    
        public double getWidth() {
            return width;
        }
    }
    

    Square

    public class Square implements Quadrilateral {
        private double side;
        public double getSide() {
            return side;
        }
        public void setSide(double side) {
            this.side = side;
        }
        public double getLength() {
            return side;
        }
        public double getWidth() {
            return side;
        }
    }
    

    RectangleDemo

    public class RectangleDemo {
        public static void main(String[] args) {
            // 创建长方形对象
            Rectangle r = new Rectangle();
            r.setLength(20);
            r.setWidth(10);
            // 调用方法进行扩宽操作,这里把对象的类型限制死了,它不能是正方形
            resize(r);
            printLengthAndWidth(r);
        }
    
        // 扩宽的方法
        public static void resize(Rectangle rectangle) {
            // 判断宽如果比长小,进行扩宽的操作
            while (rectangle.getWidth() <= rectangle.getLength()) {
                rectangle.setWidth(rectangle.getWidth() + 1);
            }
        }
    
        // 打印长和宽
        public static void printLengthAndWidth(Quadrilateral quadrilateral) {
            System.out.println(quadrilateral.getLength());
            System.out.println(quadrilateral.getWidth());
        }
    }
    

    3 测试结果

    20.0
    21.0
    
    展开全文
  • 主要介绍了Java的设计模式中里氏替换原则的意义,文中举例来说明里氏替换原则中强调的继承特性方面可能带来的问题,需要的朋友可以参考下
  • 里氏替换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。里氏替换原则是实现...
  • 里氏替换原则解析

    2013-06-08 20:08:14
    详细介绍里氏替换原则的由来和效用 里氏替换在面向对象里面是一个重要概念,用来限制继承的使用,继承作为面向对象三大机制之一,虽然带来诸多优点,但也不可避免的有缺憾,而里氏替换就是叫我们如何避免继承给代码...
  • 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第3篇,里氏替换原则LSP(The Liskov Substitution Principle )。
  • 里氏替换原则的定义有: 如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都替换成o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型。 定义很完备,但也不太好...
  • 里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;单一职责原则告诉我们实现类要职责单一;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合度;合成复用...

    在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据 7 条原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。

    这 7 种设计原则是软件设计模式必须尽量遵循的原则,各种原则要求的侧重点不同。其中,开闭原则是总纲,它告诉我们要对扩展开放,对修改关闭;里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;单一职责原则告诉我们实现类要职责单一;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合度;合成复用原则告诉我们要优先使用组合或者聚合关系复用,少用继承关系复用。

     

    1、开闭原则

    原则定义:

    软件实体应当对扩展开放,对修改关闭,这就是开闭原则的经典定义。
    
    这里的软件实体包括以下几个部分:
    1.项目中划分出的模块
    2.类与接口
    3.方法
    
    开闭原则的含义是:当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。

    实现原理:

    可以通过“抽象约束、封装变化”来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。
    
    因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。

    实例展示:

    /**
     * 定义课程接口
     */
    public interface ICourse {
        String getName();  // 获取课程名称
        Double getPrice(); // 获取课程价格
        Integer getType(); // 获取课程类型
    }
    
    /**
     * 英语课程接口实现
     */
    public class EnglishCourse implements ICourse {
    
        private String name;
        private Double price;
        private Integer type;
    
        //省略get,set,空参,满参
    }
    
    // 测试
    public class Main {
        public static void main(String[] args) {
            ICourse course = new EnglishCourse("小学英语", 199D, "Mr.Zhang");
            System.out.println(
                    "课程名字:"+course.getName() + " " +
                    "课程价格:"+course.getPrice() + " " +
                    "课程作者:"+course.getAuthor()
            );
        }
    }

    项目上线,但是出现了节假日打折的情况出现,现在有以下这几种方法去修改:

    1:修改接口(不可取,修改接口时其他的代码也得改!)

    2:修改实现类(不可取,这样会有两个获取价格的方法!)

    3:扩展实现方法(可取,不改变原有代码,功能可实现!)

    直接添加一个子类 SaleEnglishCourse ,重写 getPrice()方法,这个方案对源代码没有影响,符合开闭原则,所以是可执行的方案

    public class SaleEnglishCourse extends EnglishCourse {
    
        public SaleEnglishCourse(String name, Double price, String author) {
            super(name, price, author);
        }
    
        @Override
        public Double getPrice() {
            return super.getPrice() * 0.85;
        }
    }

    开闭原则的作用

    开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性和延续性。具体来说,其作用如下。
    
    1. 对软件测试的影响
    软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。
    2. 可以提高代码的可复用性
    粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。
    3. 可以提高软件的可维护性
    遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。

     

    2、里氏替换原则

    原则定义:

    继承必须确保超类(被继承的类称为超类,继承的类称为子类)所拥有的性质在子类中仍然成立。
    
    里氏替换原则主要阐述了有关继承的一些原则,也就是什么时候应该使用继承,什么时候不应该使用继承,以及其中蕴含的原理。里氏替换原是继承复用的基础,它反映了基类与子类之间的关系,是对开闭原则的补充,是对实现抽象化的具体步骤的规范。

    实现原理:

    1、子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
    2、子类可以有自己的个性
    3、覆盖或实现父类的方法时输入参数可以被放大
    4、覆写或实现父类的方法时输出结果可以被缩小

    实例展示:

    1、子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
    子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法,父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。
    (略)
    
    2、子类可以有自己的个性
    在继承父类属性和方法的同时,每个子类也都可以有自己的个性,在父类的基础上扩展自己的功能。前面其实已经提到,当功能扩展时,子类尽量不要重写父类的方法,而是另写一个方法,所以对上面的代码加以更改,使其符合里氏替换原则。
    (略)
    
    3、覆盖或实现父类的方法时输入参数可以被放大
    当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
                                                    (String 继承于CharSequence)
    public class ParentClazz {
        public void say(String str) {
            System.out.println("parent execute say " + str);
        }
    }
    
    public class ChildClazz extends ParentClazz {
        public void say(CharSequence str) {
            System.out.println("child execute say " + str);
        }
    }
    // 执行结果:
    // parent execute say hello
    // parent execute say hello
    // 参数大小不一样,一直用的都是string,父类的
    
    4、覆写或实现父类的方法时输出结果可以被缩小
    当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
    public abstract class Father {
        public abstract Map hello();
    }
    
    public class Son extends Father {
        @Override
        public Map hello() {
            HashMap map = new HashMap();
            System.out.println("son execute");
            return map;
        }
    }
    

    里式替换的作用:

    里氏替换原则是实现开闭原则的重要方式之一。
    它克服了继承中重写父类造成的可复用性变差的缺点。
    它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。

     

    3、依赖倒置原则

    原则定义:

    依赖倒置原则的原始定义为:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。其核心思想是:要面向接口编程,不要面向实现编程。
    
    依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。
    
    由于在软件设计中,细节具有多变性,而抽象层则相对稳定,因此以抽象为基础搭建起来的架构要比以细节为基础搭建起来的架构要稳定得多。这里的抽象指的是接口或者抽象类,而细节是指具体的实现类。
    
    使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给它们的实现类去完成。

    实现原理:

    依赖倒置原则的目的是通过要面向接口的编程来降低类间的耦合性,所以我们在实际编程中只要遵循以下4点,就能在项目中满足这个规则。
    每个类尽量提供接口或抽象类,或者两者都具备。
    变量的声明类型尽量是接口或者是抽象类。
    任何类都不应该从具体类派生。
    使用继承时尽量遵循里氏替换原则。

    实例展示:

    public class T2 {
        public static void main(String[] args) {
            IDriver zhangsan = new Driver();
            Icar benz = new Benz();
            zhangsan.drive(benz);
    
            Icar bmw = new BMW();
            zhangsan.drive(bmw);
        }
    }
    
    interface IDriver {
        //    司机职责就是驾驶汽车
        public void drive(Icar car);
    }
    
    class Driver implements IDriver{
        //    司机职责就是驾驶汽车
        @Override
        public void drive(Icar car) {
            car.run();
        }
    }
    
    interface Icar {
        //    车的作用就是跑
        public void run();
    }
    
    class Benz implements Icar {
        //    车的作用就是跑
        @Override
        public void run() {
            System.out.println("奔驰车跑起来了");
        }
    }
    
    class BMW implements Icar {
        //    车的作用就是跑
        @Override
        public void run() {
            System.out.println("宝马车跑起来了");
        }
    }

    依赖倒置原则作用:

    依赖倒置原则的主要作用如下。
    依赖倒置原则可以降低类间的耦合性。
    依赖倒置原则可以提高系统的稳定性。
    依赖倒置原则可以减少并行开发引起的风险。
    依赖倒置原则可以提高代码的可读性和可维护性。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 一个违反里氏替换原则的例子、一个遵守里氏替换原则的例子。 // 绘制图形 void drawShape(Shape shape) { if (shape.type == Shape.Circle) { drawCircle((Circle) shape); } else if (shape.type == Shape....

    只看概念比较抽象,先上实例。一个违反里氏替换原则的例子、一个遵守里氏替换原则的例子。

    // 绘制图形
    void drawShape(Shape shape) {
    	if (shape.type == Shape.Circle) {
    		drawCircle((Circle) shape);
    	} else if (shape.type == Shape.Square) {
    		drawSquare((Square) shape);
    	} else {
    		......
    	}
    	// 新增图像必需要修改drawShape方法,添加if判断来支持新的图形,违反了开闭原则
    	// 同样是因为新增图像必需要修改drawShape方法,违反了里氏替换原则
    }
    
    // 在基类Shape中定义一个抽象方法
    public abstract Shape {
    	public abstract draw();
    }
    // 然后修改drawShape方法
    void drawShape(Shape shape) {
    	shape.draw();
    }
    // 这样优化使drawShape既满足开闭原则又满足里氏替换原则。在使用基类的这个方法中可以用子类替换,程序正常运行(这就是里氏替换设计原则)
    

    理解
    在一块业务逻辑需要依赖另外一块业务逻辑的场景中,不直接依赖具体的实现,而是依赖其基类的接口方法或抽象方法,
    BUT。。。。。在业务逻辑执行时可用子类替换基类,这种设计原则就叫做里氏替换原则
    其实,里氏替换原则的原理就是利用了多态特性。通俗地说,接口或者抽象类的多个实现就是多态。通过多态可以实现面向接口进行编程,在程序运行时绑定具体的实现类,从而实现了类之间不需要直接耦合,就可以实现关联。
    里氏替换原则是一种类的继承关系设计原则

    一句话总结:子类必须可以替换掉基类,并且不影响使用基类使用方

    展开全文
  • 里氏替换原则(Liskov Substitution Principle)在1988年,由麻省理工学院的一位姓里的女士提出的。指的是 任何基类可以出现的地方,子类一定可以出现 。 核心内容: 继承必须确保超类所拥有的性质在子类中仍然...

    目录

     

    1、面向对象(oo)中继承的思考和说明

    2、里氏替换原则基本介绍

    3、应用实例

    3.1、需求

    3.2、传统方式实现

    3.2.1、类图

    3.2.2、代码

    3.2.3、传统方式分析

    3.3、遵循里氏替换原则实现

    3.3.1、设计思路

    3.3.2、类图

    3.3.3、代码

    3.3.4、里氏替换原则总结


    1、面向对象(oo)中继承的思考和说明

    • 继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏
    • 继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障
    • 那么我们在编程当中,如何正确的使用继承呢?   答案是:遵循里氏替换原则

    2、里氏替换原则基本介绍

    • 里氏替换原则(Liskov Substitution Principle)在1988年,由麻省理工学院的一位姓里的女士提出的。指的是任何基类可以出现的地方,子类一定可以出现
    • 核心内容:继承必须确保超类所拥有的性质在子类中仍然成立也就是说在继承时,子类中不要去重写父类中已实现的方法
    • 如果每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象
    • 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
    • 里氏替换原则告诉我们,继承实际上让两个类耦合性增加了,在适当的情况下,可以通过聚合,组合,依赖来解决问题。

    3、应用实例

    3.1、需求

    • 电脑类:完成求和(a+b)的功能
    • 笔记本电脑类:完成求和再求差(a+b-c)的功能
    • 笔记本电脑类中可以使用电脑类中的求和方法

    3.2、传统方式实现

    3.2.1、类图

    3.2.2、代码

    /**
     * 客户端
     */
    public class Client {
        public static void main(String[] args) {
            Computer computer = new Computer();
            System.out.println("1+2="+computer.calculate(1,2));
            
            NotebookComputer notebookComputer = new NotebookComputer();
            System.out.println("1+2-3="+notebookComputer.notebookCalculate(1,2,3));
        }
    }
    
    /**
     * 电脑
     */
    class Computer{
        public int calculate(int num1,int num2){
            //求和
            return num1 + num2;
        }
    }
    
    /**
     * 笔记本电脑
     */
    class NotebookComputer extends Computer{
        public int notebookCalculate(int num1,int num2,int num3){
            //先求和  在求差
            return calculate(num1,num2) - num3;
        }
    }

    运行结果:

    3.2.3、传统方式分析

    上面的代码设计符合基本需求,但是:如果程序员在NotebookComputer(笔记本电脑类)中将父类Computer(电脑类)中的求和方法calculate无意间重写了(这是程序员无意识的,刚好写了一个与父类的caculate方法一样的方法),会发生什么呢?

    看代码:其他的不变,只更改了NotebookComputer(笔记本电脑类)

    /**
     * 笔记本电脑
     */
    class NotebookComputer extends Computer{
    
        //程序员无意间重写了求和方法,使其实现的功能发生了改变
        @Override
        public int calculate(int num1, int num2) {
            //父类的calculate是作加法,这里是作减法
            return num1 - num2;
        }
    
        public int notebookCalculate(int num1, int num2, int num3){
            //先求和  在求差
            return calculate(num1,num2) - num3;
        }
    }

    运行结果:

    可见,这种继承是有很大几率出现问题的。当然,会出现的问题不只是上面的一种。

    里氏替换原则的出现,就是为了解决诸如此类的问题。

    3.3、遵循里氏替换原则实现

    3.3.1、设计思路

    • 给电脑(Computer)和笔记本电脑(NotebookComputer)找一个公共的父类:电子产品(Electronics);
    • 电子产品类(Electronics)中可以写电脑和笔记本共有的特性;
    • 电脑和笔记本电脑之间的关系不再是继承,而是依赖(笔记本电脑中会用到电脑)

    3.3.2、类图

    3.3.3、代码

    /**
     * 客户端
     */
    public class Client {
        public static void main(String[] args) {
            Computer computer = new Computer();
            System.out.println("1+2="+computer.calculate(1,2));
    
            NotebookComputer notebookComputer = new NotebookComputer();
            System.out.println("1+2-3="+notebookComputer.calculate(1,2,3));
        }
    }
    
    /**
     * 电子产品类
     */
    class Electronics{
        //可以写电脑与笔记本电脑共有的特征
    }
    
    /**
     * 电脑类
     */
    class Computer extends Electronics{
        /**
         * 加法
         */
        public int calculate(int num1 ,int num2){
            return num1 + num2;
        }
    }
    
    /**
     * 笔记本电脑类
     */
    class NotebookComputer extends Electronics{
        //依赖Computer类
        private Computer computer = new Computer();
    
        /**
         * 先加法 后减法
         */
        public int calculate(int num1 ,int num2,int num3){
            return computer.calculate(num1,num2) - num3;
        }
    }
    

    运行结果:

    3.3.4、里氏替换原则总结

    遵循里氏替换原则设计类的继承体系,可以避免前面所说的诸多问题。

    里氏替换原则,简单用一句话来说就是:继承不重写、重载,父类出现的地方子类一定能出现,尽可能变继承为依赖。

     

     

    本篇为我个人的理解思考与总结,有误之处请指出,谢谢 ^_^。

    展开全文
  • Java设计模式-里氏替换原则

    千次阅读 2019-03-03 10:41:14
    里氏替换原则【Liskov Substitution Principle】
  • java继承时,需要遵循里氏替换原则(Liskov Substitution Principle,LSP) 定义 如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变 化...
  • 里氏替换原则的理解: 对于里氏替换原则的四个重要特性: 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。 子类中可以增加自己特有的方法。 当子类的方法重载父类的方法时,方法的前置条件(即方法的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,680
精华内容 12,672
关键字:

里氏替换原则