zoukankan      html  css  js  c++  java
  • 里氏替换原则

    什么是里氏替换原则?

    假设每种类型T1对象O1,这两种类型T2对象O2。因此,要T1定义的所有程序P在所有对象O1都代换成O2时,程序P没有变化。那么类型T2是类型T1的子类。也就是说,一个软件实体假设使用的是一个基类的话,那么一定适用其子类。

    比喻:

    public class A {
    }
    
    public class B extends A {
    }

    
    
    public class Tests {
    
        @Test
        public void tests() {
            A a = new A();
            method(a);
    
    
            B b = new B();
            method(b);
    
    
        }
    
        public void method(A a) {
    
        }
    }
    当B是A的子类时。假设有方法method(A a),那么method(new B())也一定成立

    里氏代换原则是继承利用的基石。


    这里来聊聊西方一个很有名的样例,正方形是否是长方形的子类的总是。

    public class Rectangle {
    
        private long width;
        private long height;
    
        public long getWidth() {
            return width;
        }
    
        public void setWidth(long width) {
            this.width = width;
        }
    
        public long getHeight() {
            return height;
        }
    
        public void setHeight(long height) {
            this.height = height;
        }
    }
    当width和height相等时。就得到正方形了,由于能够理解为长方形的对象中有一些是正方形,这样理解对吗?

    那我们来看看正方形的源代码

    public class Square {
        private long side;
    
        public long getSide() {
            return side;
        }
    
        public void setSide(long side) {
            this.side = side;
        }
    }
    从上面的代码能够看出来。事实上正方形并非长方形的子类。

    事实上正方形不能够作为长方形的子类。为什么了?

    如果我们如今有个类Square是Rectange的子类,例如以下:

    public class Square extends Rectangle {
        private long side;
    
        public long getSide() {
            return side;
        }
    
        public void setSide(long side) {
            this.side = side;
        }
    
        @Override
        public long getHeight() {
            return getSide();
        }
    
        @Override
        public long getWidth() {
            return getSide();
        }
    
        @Override
        public void setHeight(long height) {
            setSide(height);
        }
    
        @Override
        public void setWidth(long width) {
            setSide(width);
        }
    }
    

    仅仅要width和height被赋值。那么width和height也会同一时候被复制,当定义一个resize方法,这种方法会将宽度不断添加,直到超过长度才停下来,假设传入的是一个Rectangle的话,这种方法没有问题。假设传入的是square的话,这种方法会引起溢出。


    public class Tests {
    
        public void resize(Rectangle rectangle) {
            while (rectangle.getHeight() <= rectangle.getWidth()) {
                rectangle.setWidth(rectangle.getWidth() + 1);
            }
        }
    }


    
    
    
    

    所以正方形不能够当成长方方形的子类。

    ok,我们对代码进行重构下,正方形和长方形都 是四边形。那们发明一个加边形类。将长方形和正方形变成它的详细子类,这样就攻克了长方形和正方形的关系不符合里氏代换原则的问题。

    public interface QuadRange {
    
        public long getWidth();
    
        public long getHeight();
    }

    public class Rectangle implements QuadRange {
    
        private long width;
        private long height;
    
        public long getWidth() {
            return width;
        }
    
        public void setWidth(long width) {
            this.width = width;
        }
    
        public long getHeight() {
            return height;
        }
    
        public void setHeight(long height) {
            this.height = height;
        }
    }

    public class Square implements QuadRange {
        private long side;
    
        public long getSide() {
            return side;
        }
    
        public void setSide(long side) {
            this.side = side;
        }
    
    
        @Override
        public long getWidth() {
            return getSide();
        }
    
        @Override
        public long getHeight() {
            return getSide();
        }
    <span style="font-family: Arial, Helvetica, sans-serif;">这样在基类里没有赋值方法,因此resize的方法就不能合适于QuadRange这种基类,而仅仅能适合于不同的详细子类Rectangle和Square,这样里氏代换原则不可能被破坏.</span>








    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    RAID-磁盘阵列
    Redis-Cluster 5.0.4 集群部署
    linux系统磁盘缩容
    MongoDB Replica Set 集群
    CentOS7 GlusterFS文件系统部署
    CentOS7 firewalld防火墙规则
    centos7 升级openssh到openssh-8.0p1版本
    MySQL 中操作excel表格总结
    超哥带你学GIT
    学习是主动吃苦
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4751081.html
Copyright © 2011-2022 走看看