我相信从学习计算机面向对象编程起就很多人背下了继承、封装、多态三个特性,可是多态并不是那么好理解的。通常做几道题,背下几次多态的动态绑定规律,可是依旧在一段时间后忘记了多态的存在,为什么要多态,这个程序为何会产生这样的结果呢?

  先看多态的两个必要条件:继承、重写。

  thinking in java 中对继承有提到:通过继承而产生的类型等价是理解面向对象程序设计方法的重要门槛,他们有相同的基础接口,而对应的接口也必然有某些具体的实现,因为继承是产生了新的类型,如果新类型没有什么不同的行为,那继承就没有什么意义。对外来说,如果要做到不同的行为实现,那就要进行接口的重写,使得消息传递到该对象的时候,能产生不同的行为。而选择不同行为的过程,其实就是我们常说的动态绑定,其实在内存来说,就是jvm到底要跑哪一部分代码块。

  本文不打算说编译时多态。

  那么运行时多态到底如何设置绑定规则呢?其实是从问题空间来的,我们知道,继承要有意义,而且是的代码具有拓展性,必然要符合问题空间,具体来说可以是基础设施,也可以是领域模型;因此我们泛化一个类型的时候,总是希望利用基类型用作统一处理所有业务,然后让不同的实现类去做具体的事情,因此有如下的规则:

  1、先从声明类型(基类)入手,寻找所有其向上型(父类,超类)的接口实现,寻找对应可绑定代码,保证泛化类型行为的正确性(也就是这样找才可以保证类型等价),如果2不成立,则根绝消息参数执行对应的接口实现(这里的要根据消息参数是因为消息参数也有向上转型情况)。

  2、如果该接口被重写,那么执行被重写的方法,原因很简单,任何时候this指针是指向实际类型的,也就是问题空间中继承出的新类型,已经重新定义了该行为,所以必须绑定重写的行为。这一点是多态的意义所在。

  其实以上两点和提到的继承重写可以引申到里氏替换原则(不要问我为什么要符合里氏替换),为符合重写的规则,本身java就保证了前置条件和后置条件,即继承并且覆盖超类方法的时候,子类中的方法的可见性必须等于或者大于超类中的方法的可见性,子类中的方法所抛出的受检异常只能是超类中对应方法所抛出的受检异常的子类,但是要维持is-a关系,使得抽象类型是符合开闭原则的,本身就要求多态是不能瞎用的,所以多态也要记住一个原则:

  3、里氏替换原则。

  第二点充分说明了一个问题,在你向上转型的时候,完全不用担心你子类重写的行为会消失,基类只保证类型,而子类优先行为。

  下面给出个具体例子。。。。。。

面向对象编程之Java多态的更多相关文章

  1. PHP面向对象编程之深入理解方法重载与方法覆盖(多态)

    这篇文章主要介绍了PHP面向对象编程之深入理解方法重载与方法覆盖(多态)的相关资料,需要的朋友可以参考下: 什么是多态? 多态(Polymorphism)按字面的意思就是"多种状态" ...

  2. python基础-面向对象编程之多态

    面向对象编程之多态以及继承.抽象类和鸭子类型三种表现形式 多态 定义:同一种类型的事物,不同的形态 作用: 多态也称之为"多态性".用于在不知道对象具体类型的情况下,统一对象调用方 ...

  3. 深入理解JavaScript系列(17):面向对象编程之概论

    介绍 在本篇文章,我们考虑在ECMAScript中的面向对象编程的各个方面(虽然以前在许多文章中已经讨论过这个话题).我们将更多地从理论方面看这些问题. 特别是,我们会考虑对象的创建算法,对象(包括基 ...

  4. Java 多态——与C++的比较

    学习了Java和C++之后,由于长期不使用C++,而java的基础知识掌握不牢,现在已经搞不清java多态了.现在先来谈谈java多态,稍后有时间再更新C++的多态,并进行比较~ 一. Java的多态 ...

  5. C++和java多态的区别

    C++和java多态的区别 分类: Java2015-06-04 21:38 2人阅读 评论(0) 收藏 举报  转载自:http://www.cnblogs.com/plmnko/archive ...

  6. 深入理解Java多态机制

    从字节码层面来看,Java中的所有方法调用,最终无外乎转换为如下几条调用指令. invokestatic: 调用静态方法. invokespecial: 调用实例构造器<init>方法,私 ...

  7. Java 多态 父类和子类方法的访问控制权限

    Java 多态 父类和子类方法的访问控制权限 @author ixenos 父类和子类方法的访问控制权限 继承是为了扩展类的功能,而这种扩展显然就是对一个原始类的扩展,目的还是向上转型来调用,所以这就 ...

  8. Java多态(二)

    public class ExtendsTest { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); ...

  9. 从JVM角度看Java多态

    首先,明确一下,Java多态的三个必要条件: 1. 继承 2. 子类重写父类方法 3. 父类引用指向子类对象 然后看一个例子 package test.xing; class Father{ prot ...

随机推荐

  1. Android如何实现茄子快传

    Android如何实现茄子快传茄子快传是一款文件传输应用,相信大家都很熟悉这款应用,应该很多人用过用来文件的传输.它有两个核心的功能: 端到端的文件传输Web端的文件传输这两个核心的功能我们具体来分析 ...

  2. 集群安装Java环境

    需要安装一个集群环境,发现全部要手动安装java.记录下安装Java环境的过程.虽然,依旧是挨个安装,但总算是有体系了. java 找到下载地址: https://www.oracle.com/tec ...

  3. NOIP2012 普及组 寻宝

    题目描述 Description 传说很遥远的藏宝楼顶层藏着诱人的宝藏.小明历尽千辛万苦终于找到传说中的这个藏宝楼,藏宝楼的门口竖着一个木板,上面写有几个大字:寻宝说明书.说明书的内容如下: 藏宝楼共 ...

  4. lua变量作用域

    3.5 – Visibility Rules Lua is a lexically scoped language. The scope of a local variable begins at t ...

  5. 【Android】解析Paint类中Xfermode的使用

    Paint类提供了setXfermode(Xfermode xfermode)方法,Xfermode指明了原图像和目标图像的结合方式.谈到Xfermode就不得不谈它的派生类PorterDuffXfe ...

  6. Jmeter执行python脚本函数使用说明

    一.下载地址插件百度网盘下载地址:https://pan.baidu.com/s/1SvJjyThsXYryXuEEg9rm3g提取码:q9hd 二.使用说明1.将下载的jmeter-function ...

  7. Linux下通过server-status监控性能

    Linux下通过server-status监控性能 前提:安装好Apache,在opt/路径下 查看Apache的工作模式 可以知道是 prefork.c模式 配置server-status 性能 进 ...

  8. 深入理解Linux内存分配

    深入理解Linux内存分配 为了写一个用户层程序,你也许会声明一个全局变量,这个全局变量可能是一个int类型也可能是一个数组,而声明之后你有可能会先初始化它,也有可能放在之后用到它的时候再初始化.除此 ...

  9. django项目settings.py的基础配置

    一个新的django项目初始需要配置settings.py文件: 1. 项目路径配置 新建一个apps文件夹,把所有的项目都放在apps文件夹下,比如apps下有一个message项目,如果不进行此项 ...

  10. 如何添加使用echats地图悬浮显示内容

    /初始化绘制全国地图配置 var option = { backgroundColor: '#000', title: { text: 'Echarts3 中国地图农村金融', subtext: '三 ...