里氏代换原则

什么是里氏代换原则了?

如果对于每一个类型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>








  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值