软件构造:对于Liskov替换原则的理解

目录

前言

定义

Java中的Liskov原则

对于协变(co-variant)

对于逆变(contravariance)

总结


前言

        这是我对于Liskov原则的定义和相关概念,以及我自己的理解进行的概述。

定义

        Liskov原则是一个关于设计父类和子类关系的原则。

        由Barbara Liskov的话来定义该原则:

如果对于类型T的对象x,q(x)成立,那么对于类型T的子类型S的对象y,q(y)也成立。

这个定义比较抽象,我们可以在Java中的上下文中来尝试理解它。

Java中的Liskov原则

        在Java中,Liskov原则可以理解为以下一系列要求:

1.某一类型T的子类型S可以增加新方法,但是不能删除类型T的方法。
2.子类型T需要实现抽象类型中未实现的方法。抽象类型可以指的是类型T实现的接口(implements),也可以指的是一个抽象类(extends)。
3.子类型中重写的方法的返回值类型必须与父类/接口的返回值类型相同或者是它的子类型,即协变(co-variant)的类型。---对重写方法返回值类型的要求。
4.子类型重写方法的参数类型要么相同要么是逆变(反协变)的,对于后者java会认为是重载方法而非重写方法。---对重写方法参数类型的要求。
5.子类型中不能抛出额外的异常。
6.对于这些子类型/它们重写的方法的规约,要求更强或相同的不变量、更弱或不变的前置条件、更强或不变的后置条件。


对于协变(co-variant)

        指的是父类和子类中对应方法的对应返回值类型/异常类型的一种变化:即由父类到子类,越来越具体,对应的返回值类型/异常类型也越来越具体。如下:

                                                

        子类中对应方法的返回值类型变成String(Object是它的超类),更加“具体”了。

                                                 

        子类型抛出的异常更加“具体”,IOException是Throwable的子类。

对于逆变(contravariance)

        从父类型到子类型,越来越具体,但是对应方法的参数类型越来越抽象。

        注意,从父类到子类,参数类型是可以协变的,但是这样是不安全的,因为协变的参数类型意味着,随着类的具体化,对应方法的输入更加“窄”了,这是不合理的。

                                             

        可以看到,子类型的参数类型是Object(String的超类),更加“具体"了。

        但是要注意的的是这个子类”重写“的方法上加了一个Override标签,这会导致编译错误,因为java要求重写方法的签名必须和父类是完全一致的!也就是说java并不支持重写方法中参数类型的逆变,去掉Override标签之后,Java会将该方法视作对子类继承自父类方法的重载。(也就是说,如果父类还没有实现这个方法,你还得去实现它)。

总结

        我们可以用下面这张图作为对以上内容的总结:

        T'指向T意味着T'类是T类的子类。

        在子类的实现中,比较保守的方法是第二种,所有方法的返回值类型和参数类型都和父类的一致。

        注意到Java支持子类重写方法中返回值类型的协变,但是并不支持重写方法中参数类型的逆变或者协变,后者甚至是不安全的,因为这会带来更具体的实现、但更窄的输入。

        当我们声明变量用的是父类,而实例类型是它的子类时,协变的参数类型会带来潜在的风险,因为我们在把它当作父类来使用。

        以上就是我对于Liskov原则及相关概念的概述。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值