原创 设计模式:七大原则之里氏替换原则

发布时间:2021-06-24 13:28:52 浏览 329 来源:猿笔记 作者:久眠深巷

    ####OO中的继承性的思考和说明,父类中凡是已经实现好的方法。实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约。但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏,-继承在给程序设计带来便利的同时,比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,则当这个类需要修改时,必须考虑到所有的子类?所有涉及到子类的功能都有可能产生故障,如何正确的使用继承(里氏替换原则)。使得以T1定义的所有程序P在所有的对象O1都代换成O2时,程序P的行为没有发生变化。


    #主题列表:juejin,github,smartblue,cyanosis,channing-cyan,fancy,hydrogen,condensed-night-purple,greenwillow,v-green,vue-pro,healer-readable,mk-cute,jzman,geek-black,awesome-green,qklhk-chocolate

    #投稿主题:

    theme:github

    highlight:

    面向对象中继承的思考与解释

    -继承包含这样一个含义:父类中所有实现的方法实际上都是在设置规范和契约。虽然并不强制所有子类都遵循这些契约,但是如果子类任意修改这些实现的方法,整个继承系统就会受损。

    -继承不仅给编程带来了方便,也带来了弊端。比如继承的使用会给程序带来入侵性,降低程序的可移植性,增加对象之间的耦合性。如果一个类被其他类继承,当这个类需要修改时,必须考虑所有子类,父类修改后,所有涉及子类的函数都可能失效

    问题:编程中如何正确使用继承(Richter替换原理)?

    # #基本介绍

    -里氏替换原则(LiskovSubstitutionPrinciple)在1988年,由麻省理工学院的一位姓里的女士提出。

    如果对于T1类型的每个对象O1都有一个T2类型的对象O2,使得当所有对象O1被O2替换时,T1定义的所有程序P的行为不变,那么T2类型是T1类型的子类。* *换句话说,所有引用基类的地方都必须透明地使用它的子对象* *。

    -使用继承时,遵循Richter替换原则,尽量不要重写* *子类中父类的方法。

    ——Richter置换原理告诉我们,继承实际上增强了两个类之间的耦合,在适当的情况下,问题可以通过聚合、组合、依赖来解决

    ##应用实例packagecom.braveway.principle.liskov;

    publicclassLiskov{

    \tpublicstaticvoidmain(String[]args){

    \t\tAa=newA();

    \t\tSystem.out.println("11-3="+a.func1(11,3));

    \t\tSystem.out.println("1-8="+a.func1(1,8));

    \t\t

    \t\tSystem.out.println("------------");

    \t\tBb=newB();

    \t\tSystem.out.println("11-3="+b.func1(11,3));//这里本意是求出11-3

    \t\tSystem.out.println("1-8="+b.func1(1,8));//1-8

    \t\tSystem.out.println("11+3+9="+b.func2(11,3));

    \t}

    }

    //A类

    classA{

    \t//返回两个数的差

    \tpublicintfunc1(intnum1,intnum2){

    \t\treturnnum1-num2;

    \t}

    }

    //B类继承了A

    //添加了一个新函数:将两个数字相加,然后与9相加

    classBextendsA{

    \t

    \t//这里重写了a类的方法,可能是无意识的

    \tpublicintfunc1(inta,intb){

    \t\treturna+b;

    \t}

    \t

    \tpublicintfunc2(inta,intb){

    \t\treturnfunc1(a,b)+9;

    \t}

    }

    # #解决方法

    -我们发现正常运行的减法有错误。意愿在于B类不经意重写了父类的方法,导致原函数出错。在实际编程中,我们经常通过重写父类来完成新的函数,编写简单,但是整个继承系统的可重用性较差。尤其是频繁运行多态的时候。

    -通常的做法是,原父类和子类继承一个更流行的基类,去掉原继承关系,这样就可以替换依赖、聚合、组合等关系

    ##应用实例packagecom.braveway.principle.liskov.improve;

    publicclassLiskov{

    \tpublicstaticvoidmain(String[]args){

    Aa=newA();

    System.out.println("11-3="+a.func1(11,3));

    System.out.println("1-8="+a.func1(1,8));

    System.out.println("-------------");

    Bb=newB();

    //因为b类不再继承a类,

    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

    \t}

    }

    //创建一个更基本的基类

    classBase{

    \t//将更多基本方法和成员写入基类

    }

    //A类

    classAextendsBase{

    \t//返回两个数的差

    \tpublicintfunc1(intnum1,intnum2){

    \t\treturnnum1-num2;

    \t}

    }

    //B类继承了Base类

    classBextendsBase{

    \t//如果b需要使用a类的方法,则使用组合关系

    \tprivateAa=newA();

    \t

    \t//这里重写a类的方法可能是无意识的

    \tpublicintfunc1(inta,intb){

    \t\treturna+b;

    \t}

    \t

    \tpublicintfunc2(inta,intb){

    \t\treturnfunc1(a,b)+9;

    \t}

    \t

    \t//我们还是要用a的方法。

    \tpublicintfunc3(inta,intb){

    \t\treturnthis.a.func1(a,b);

    \t}

    }

作者信息

久眠深巷 [等级:3] 后端开发工程师
发布了 14 篇专栏 · 获得点赞 1 · 获得阅读 1138

相关推荐 更多