zoukankan      html  css  js  c++  java
  • Java中多态是否违背了里氏替换原则

    问题产生原因:

    ​ 里氏替换原则:子类对象能够替换父类对象,而程序逻辑不变,要求子类避免重写父类方法。

    ​ 多态存在条件之一:要求子类重写父类的方法。

    问题解释:

    LSP 的原定义比较复杂,一般对里氏替换原则 LSP 的解释为:子类对象能够替换父类对象,而程序逻辑不变。

    这一原则是针对继承而言的,所以本质上是普遍性与特殊性的关系:普遍性孕育于所有的特殊性中,特殊性违背不了普遍性。普遍性一旦被特殊化就不再是普遍性,这势必影响所有的特殊性。所以,就程序设计而言,子类不可修改父类。

    里氏代换原则就是上述规律的结论:程序中对普遍性的依赖,可以由特殊性满足,因为特殊性中蕴含着普遍性。也就是:子类能够替换父类,而程序逻辑不变。

    里氏转换原则要求子类从抽象继承而不是从具体继承,如果从抽象继承,子类必然要重写父类方法。因此里氏转换原则和多态是相辅相成的。

    而要满足里氏代换原则,本质上就是要让代码设计符合上述规律:特殊性不可违背普遍性,也就是子类不可修改父类。所以,实现继承时,父级应当是抽象类或者接口,而不能是可实例化的类。

    里氏替换原则,就是让你的某一段程序耦合于基类或者接口,而不是具体继承了基类的子类或实现接口的具体类型。仅替换子类不会让你这个程序的属性有所改变。

    通俗讲就是,我声明的一个类或接口,然后随意的 new 继承这个基类的子类或者实现这个接口的类。然后我随意的调用这个基类或接口的方法,程序都正确执行不出现问题。

    里氏替换原则有至少以下两种含义:

    1. 里氏替换原则是针对继承而言的,如果继承是为了实现代码重用,也就是为了共享方法,那么共享的父类方法就应该保持不变,不能被子类重新定义。子类只能通过新添加方法来扩展功能,父类和子类都可以实例化,而子类继承的方法和父类是一样的,父类调用方法的地方,子类也可以调用同一个继承得来的,逻辑和父类一致的方法,这时用子类对象将父类对象替换掉时,当然逻辑一致,相安无事。

    2. 如果继承的目的是为了多态,而多态的前提就是子类覆盖并重新定义父类的方法,为了符合 LSP,我们应该将父类定义为抽象类,并定义抽象方法,让子类重新定义这些方法,当父类是抽象类时,父类就是不能实例化,所以也不存在可实例化的父类对象在程序里。也就不存在子类替换父类实例(根本不存在父类实例了)时逻辑不一致的可能。

    不符合 LSP 的最常见的情况是,父类和子类都是可实例化的非抽象类,且父类的方法被子类重新定义,这一类的实现继承会造成父类和子类间的强耦合,也就是实际上并不相关的属性和方法牵强附会在一起,不利于程序扩展和维护。

    符合 LSP 的方法:尽量不要从可实例化的父类中继承,而是要使用基于抽象类和接口的继承。

    多态与里氏替换原则是否冲突?

    里氏替换原则要求特殊性不可违背普遍性,这个违背是指子类修改父类。而多态是指子类本身就父类中的普遍性进行特殊化的继承,实际上并未修改父类。所以,两者不冲突,是一种补充关系。多态使得父类的普遍性能够在子类中进行特殊化继承。里氏代换原则要求继承关系必须符合普遍性与特殊性的规律。

    参考:

    https://www.zhihu.com/question/27191817

  • 相关阅读:
    高效程序猿的45个习惯:敏捷开发修炼之道之主题建议翻译1-10
    VS2010旗舰版安装图解
    ibatis 使用 in 查询的几种XML写法
    人脸识别算法初次了解
    键盘过滤驱动
    python property属性
    癞子麻将胡牌算法实现
    恩布900手机客服,安卓版本号Entboost Android 1.0 正式公布
    C语言递归实现二叉树的先序、中序、后序遍历
    CSS:CSS 属性 选择器
  • 原文地址:https://www.cnblogs.com/thetree/p/13605879.html
Copyright © 2011-2022 走看看