我们前面已经介绍了面向对象编程的三大特性之二,今天就介绍最后一个特性-多态。
什么叫多态?从字面上理解就是多种形态,即对同一个客体,可以有多种不同的形式。就好像糖一样,有多种口味,你想吃什么口味的就可以吃什么口味。但在程序中,却不是你想要怎样就怎样。更多的是需要怎样去做就怎样去做。来一个算是比较官方的解释:在面向对象语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数实现的,而在java中,多态的实现主要通过方法重载和方法重写来实现的。实际上, 我们在前面说继承一章的时候,就已经使用过多态这个特性了,只是说还没有将其表现出来而已。请看我们之前定义的几个类:


你看,这是我们之前设立的两个类,看起来就是一个继承关系而已是吧。实际上,如果我们做以下操作,或许你就发现里面大有乾坤:

操作:新建一个Test类,实现以下代码:

如果单纯看右面的代码,我们会觉得说这就是一个普通的继承嘛是吧,但若仔细观察里面的代码(注释处),你会发现,在这个Test类中,执行了这么一个操作:

Animal giraffe =new Giraffe();

而这个操作我们之前真的是前所未见呀,见过最相近的应该也是这个:

Giraffe giraffe =new Giraffe();

那么,这两者有什么区别呢?其实,尽管这两行代码最后所得到的结果是一样的,但是两者却发生了本质的不同。为什么呢?因为前者就是我们要介绍的多态,而后者则是简单的创建一个Giraffe对象的过程而已。嗯,一头雾水,为什么一个Animal类型的变量能够引用Giraffe类型的对象呢?这是因为,Giraffe继承了Animal的一些特性,当我们使用Giraffe的对象时,实际上也可以理解为使用的是Animal对象,但不同的是,我们能使用的Animal对象仅限于Animal仅有的,如果超出了Animal的部分,才当做时Giraffe的自带属性,而如果我们用一个父类型去引用子类对象时,会先访问到子类中重写的父类方法(父类的方法不会再执行),如果子类没有重写父类的方法,才会执行父类中的重写办法。同时,子类中没有继承到父类的部分,是不能被执行的。什么意思呢?代码解释:
修改子类相关方法:不重写Animal类中的eat方法,增加Giraffe的run方法:

重新执行Test,结果如下:

发现了没?我们在新修改的Giraffe中并没有重写eat方法,所以它执行的是Animal中的方法,而对于已经重写的sleep方法,则执行了子类重写的部分。那么当我们打算执行run方法呢?结果如下:

你看出现了错误,意思为run方法没有在Animal类中声明。
所以,这就是我们为什么说:如果我们用一个父类型去引用子类对象时,会先访问到子类中重写的父类方法(父类的方法不会再执行),如果子类没有重写父类的方法,才会执行父类中的重写办法。同时,子类中没有继承到父类的部分,是不能被执行的。而这种调用方式,就是多态的一种状态,叫做向上转型,也是最为容易理解的一种多态方式。
那么,既然有向上转型,自然也有向下转型啦。那么有同学就说了。向上转型是子类转父类,那么向下当然就是父类转子类了,于是巴拉巴拉,把代码修改为:

Giraffe giraffe =(Giraffe) new Animal();

你们觉得这样理解对吗?我们事实说话:执行代码:

我们发现,不行,出现了ClassCastException异常,解释是说Animal类不能转化为Giraffe类。说明这个思路是错误的。那么,什么样才是正确的呢?就是:已经转为父类型的子类对象,再转回成子类型,才叫做向下转型:WTF??我要先向上转型为父类,再从父类向下转型为子类???那不是直接和调用子类对象是一样的嘛!看到这里,相信这是大多数人的心声。但实际上,这两者是有区别的,什么区别呢?就是我们可以在向上转型的过程中,对即将进行的向下转型操作进行一定的修改。什么意思呢?请看例子:我们对Animal类和Giraffe进行一定的修改,新增一个属性count,表示吃了多少顿饭。代码如下:
Animal类:

package ClassTest;
//Animal类
public class Animal {//新增一个count属性。并设置set和get方法private int count;public int getCount() {return count;}public void setCount(int count) {this.count = count;}void eat(){System.out.println("动物吃了饭");}void sleep(){System.out.println("动物睡觉");}
}

接下来是Giraffe类:

package ClassTest;
//继承自Animal类的Giraffe类
public class Giraffe extends Animal {//新增一个count属性private int count;public int getCount() {return count;}public void setCount(int count) {this.count = count;}//重写的构造方法public Giraffe(int count) {super();this.count = count;}//重写的sleep方法void sleep(){System.out.println("长颈鹿吃了"+count+"顿草");}//子类增加的方法void run(){System.out.println("长颈鹿四条腿狂跑");}}

我们先进行第一个Test,代码如下:

发现和使用

Giraffe giraffe = new Giraffe(1); 

并没有什么不同,不用怕,接下来就有改变了:

在Test类中新增代码:

你看,如此对giraffe的count属性进行修改后,是不是也影响到了giraffe2的count属性呢?这里其实就是借助先向上,再先下这个空隙来实现对数据的修改。当然这只是向下转型的一个方法,实际上向下转型更多是应用在java中的设计模式及泛型之中。而这些知识点会在以后的学习中帮助你更容易去理解多态的作用。
好了,接下来,我们对多态进行一个总结:
1、不管是向上转型,还是向下转型,我们涉及到的都是子类和父类的问题,也就是说多态必须存在继承关系

2、正如上面所说,多态就是多种形态。也就是说,当我们需要实现多态的时候,就需要有父类的方法被子类重写。否则,如果没有重写的方法,就看不出多态的特性,一切按照父类的方法来,还不如不要继承,直接在父类中添加相应的方法,然后在实例化好了

3、不管是向上转型还是向下转型,都有一个共性,就是父类指向子类对象。如果没有这个,也就没有了多态。

而关于多态的表现形式,分为两类:
静态分派,即方法的重载。表现为方法同名不同参,可以存在多个同名的方法,只要参数不一致就行,我们可以根据实际情况调用其中一个,所以称为静态分派。
动态分派,即方法的重写。表现为同名同参不同的执行操作。只能出现一个方法,而方法内部的操作时动态更改的。每次能且仅能调用一个方法。因为它并没有被人选择地特性,所以为动态。

好了,至此,面向对象的三大特性已经介绍完毕。不过需要注意的是。在这介绍的其实是不全面的一部分,可以说只算得上是入门知识。真正要对三大特性有一个了解,还需要不断去编码,学习,越往深处学,才越能懂得。否则,要是直接巴拉巴拉说得相对全面了,你也会一脸懵逼。毕竟这三大特性是贯穿整个java的,很多技术上的理解需要其他知识的相互配合去支持,不然就根本不知道说的是什么了。好了,让我们一起往java的深处行走吧,下一章是比较烧脑的一章:“java-面向对象编程-内部类”,敬请期待。

Java-面向对象编程-三大特性之多态相关推荐

  1. Day55-每日一道Java面试题-Java 面向对象编程三大特性: 封装 继承 多态

    Java 面向对象编程三大特性: 封装 继承 多态 封装 封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问.但是如果一个类没有 ...

  2. Java学习笔记二十五:Java面向对象的三大特性之多态

    Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...

  3. Python面向对象编程三大特性之多态

    多态 code:_9polymorphism.py # ***************************************** """ 多态:对于同一个方法, ...

  4. polymorphism java_Java基础-面向对象第三大特性之多态(polymorphism)

    Java基础-面向对象第三大特性之多态(polymorphism) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.多态概述 多态是继封装,继承之后,面向对象的第三大特性,多态的 ...

  5. Python - 面向对象编程 - 三大特性之继承

    继承 继承也是面向对象编程三大特性之一 继承是类与类的一种关系 定义一个新的 class 时,可以从某个现有的 class 继承 新的 class 类就叫子类(Subclass) 被继承的类一般称为父 ...

  6. 面向对象的三大特性之多态

    面向对象的三大特性之多态 文章目录 面向对象的三大特性之多态 前言 一.静态多态 1.函数重载 2.函数模板 二.动态多态 1.函数重写 2.虚函数的继承特性 三.重定义 前言 多态的简单定义为同一种 ...

  7. java面向对象特性_java面向对象编程三大特性

    一说到java面向对象编程就想到面向对象的三大特性,封装,继承和多态,下面我们来具体分析以下这三大特性在编程中是如何具体体现的. 封装 将类的属性和具体实现细节隐藏,只提供相关的接口和方法来对隐藏信息 ...

  8. java面向对象:三大特性:封装,继承,多态

    -----------------------------------面向对象:三大特性:封装,继承,多态 ----------------------------------- 1.什么是类?什么是 ...

  9. 面向对象的三大特性之多态,封装基础

    面向对象的三大特性  :  继承    多态    封装 多态:一个类表现出多种形态:通过继承来实现的 在python中:由于函数的参数不需要指定数据类型,所以也不需要通过继承的形式来统一一组类的类型 ...

  10. Java基础篇——三大特性(多态)

    这是Java三大特性的最后一篇文章,本篇主要讲解多态的概念和应用.如果是对Java有兴趣的小伙伴可以关注一下,后续会推出一系列的Java基础和进阶的总结(或者说是个人的理解吧!)可以让你学到一些基础但 ...

最新文章

  1. Redis 配置文件介绍——redis.conf
  2. 关于可观察性的三大支柱,你应该了解这些
  3. Fabio技术手册(1):概述和快速上手
  4. Python教程: 闭包及陷阱
  5. java监控网卡_VC++监控网卡状态
  6. 补丁程序正在运行_针对微软4月14日更新补丁会导致蓝屏问题的检测及解决方法...
  7. 手机客户端和服务器端通信
  8. springboot公共模块打包_解决SpringBoot多模块发布时99%的问题?
  9. 手机计算机的冷知识,重度手机控也未必知道的冷知识!现在智能手机都一个样?...
  10. 2018SDIBT_国庆个人第七场
  11. 【web前端】JavaScript闭包
  12. 从开锁到中年危机的杂谈
  13. exoplay切换全屏_如何使用rotation-degrees手动旋转(rotate)exoplayer2播放器
  14. Pandas Percentile计算方法
  15. 【运动规划】MIT 基于采样和优化的区别
  16. CASE SOLVED: ubuntu16.04 搜狗拼音中文乱码
  17. InnoDB与MyISAM的优缺点
  18. 脉冲神经网络大致流程
  19. 2019计算机考研大纲考什么,2019计算机考研大纲解析
  20. dodo:人脸识别方法个人见解(包括稀疏表示方法的理解)

热门文章

  1. 计算机上机考试的系统,计算机上机考试系统
  2. 网游开发引擎应用分析
  3. 关于破解电信光猫实现内网穿透(端口转发,端口映射)
  4. DNS Server
  5. matlab 数字波束合成,dbf数字波束合成
  6. lua 常用数据类型总结
  7. 生成pdf设置中文字体出错 \simsun.ttc' with 'Identity-H' is not recognized或者type of font{0} is not recognized
  8. Intellij IDEA 使用教程(史上最全,持续更新)
  9. 中国各省级行政区公共数据开放平台网址(2021.11.1更新)
  10. Python Django 个人博客源码(附个人源码和网站参考)