java里氏替换原则例子_java 设计原则(六)里氏替换原则

定义:如果对每一个类型T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都替换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。

定义扩展:一个软件实体如果适用一个父类的话,那一定适用于其自类,所有引用父类的地方必须能透明地使用其自类的对象,子类对象能够替换父类对象,而程序逻辑不变。

引申意义:子类可以扩展父类的功能,但不能改变父类原有的功能。

含义1:子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。

含义2: 子类可以增加自己特有的方法。

含义3:当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类的方法的输入参数更宽松。

含义4:当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输入/输出值)要比父类更严格或相等。

优点1:约束继承泛滥,开闭原则的一种体现。

优点2:加强程序的健壮性,同时变更时也可以做到非常好的兼容性提高程序的维护性、扩展性。降低需求变更时引入的风险。

public class Reactangle {

private long length;//长度

public long getLength() {

return length;

}

public void setLength(long length) {

this.length = length;

}

public long getWidth() {

return width;

}

public void setWidth(long width) {

this.width = width;

}

private long width;//宽度

}

public class Square extends Reactangle {

//正方形的边长

private long sideLength;

//getLength() =getWidth() = getSideLength()

public long getSideLength() {

return sideLength;

}

public void setSideLength(long sideLength) {

this.sideLength = sideLength;

}

//getLength() =getWidth() = getSideLength()

@Override

public long getLength() {

return getSideLength();

}

//重写了 长方形设置宽的方法 正方形是长方形的特殊形式 边和长都是一样的

//setWidth() = setLength() = setSideLength()

@Override

public void setLength(long length) {

setSideLength(length);

}

//getLength() =getWidth() = getSideLength()

@Override

public long getWidth() {

return getSideLength();

}

//重写了 长方形设置宽的方法 正方形是长方形的特殊形式 边和长都是一样的

//setWidth() = setLength() = setSideLength()

@Override

public void setWidth(long width) {

setSideLength(width);

}

}

public class Test {

//这是长方形的一个resize方法 判断宽度如果小于等于长度就增加1

public static void resize(Reactangle rectangle){

while(rectangle.getWidth() <= rectangle.getLength()){

rectangle.setWidth(rectangle.getWidth() +1);

System.out.println("Width:" +rectangle.getWidth() +"length" +rectangle.getLength());

}

System.out.println("resize方法结束:" +rectangle.getWidth() +"length" +rectangle.getLength());

}

public static void main(String[] args) {

Reactangle rectangle =new Reactangle();

rectangle.setWidth(10);

rectangle.setLength(20);

resize(rectangle);

}

}

当我们 要用 Square 扩展 这个 Reactangle 类 期望达到的是 只要重写父类的方法 按照一定的标准 适用Reactangle 这个类的方法一定也适用于Square这个类 但是 resize()这方法并不能适用于 Square 因为 resize在判断长度的时候 会比较 边长 和宽度 大小 但正方形边长都一样 这样resize 会陷入while死循环。

public static void main(String[] args) {

Square sq =new Square(10);

resize(sq);

}

上面可以看出 Square 不适合 里式替换 原则 那怎么样 设计 才能进行 约束防止继承的泛滥呢。

public interface Quadrangle {

long getWidth();

long getLength();

}

public class Reactangle implements Quadrangle {

private long length;

public void setLength(long length) {

this.length = length;

}

public void setWidth(long width) {

this.width = width;

}

private long width;

@Override

public long getWidth() {

return width;

}

@Override

public long getLength() {

return length;

}

}

public class Square implements Quadrangle {

public void setSideLength(long sideLength) {

this.sideLength = sideLength;

}

private long sideLength;

public Square(int sideLength) {

this.sideLength = sideLength;

}

@Override

public long getWidth() {

return sideLength;

}

@Override

public long getLength() {

return sideLength;

}

}

a971d17dad0a748e7e3979dd3590c49b.png

//这里传入的是四边形 类型

public static void resize(Quadrangle rectangle){

//下面会报错 因为 四边形方法里没有setWidth()方法 这样就很好的约束了 子类 的行为。 所以上面只能传入(Reactangle rectangle)

while(rectangle.getWidth() <= rectangle.getLength()){

rectangle.setWidth(rectangle.getWidth() +1);

System.out.println("Width:" +rectangle.getWidth() +"length" +rectangle.getLength());

}

System.out.println("resize方法结束:" +rectangle.getWidth() +"length" +rectangle.getLength());

}

里氏替换原则 强调子类的行为 应与父类保持一致 可以达到 子类 替换 掉父类时 功能保持 程序P的功能 能保持不变。

方法入参/返回

public class Base {

//当父类写成Map 或者HashMap 传参 都会调用子类 重写方法

public void method(HashMap map){

System.out.println("父类被执行");

}

}

public class Child extends Base {

@Override

public void method(HashMap map) {

System.out.println("子类HashMao 入参方法被执行");

}

//子类这个方法不能 比父类的 范围大 Map 比 HashMap 范围大

//所以这个方法 是不会被执行的

public void method(Map map) {

System.out.println("子类被执行");

}

}

public class Test {

public static void main(String[] args) {

Base a = new Child();

a.method(new HashMap());

}

}

同理 子类的返回 值比 父类的返回值 范围更大 就会直接报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值