2019独角兽企业重金招聘Python工程师标准>>>

多态无处不在。引用的概念最为困难。理解了引用才能理解多态的意义以及应用。

多态的应用的一大前提是继承。以及继承中的重写方法。继承的一大前提是封装,而封装里面涉及到重要知识点方法重载。
所以要领会多态,前面的封装与继承是基础。而多态也是前两者的更进一步扩展。就好像负数对正数的扩展一样,三者又一起共同构建起了面向对象的三大基本特征。
所以先来大致回忆理解一下这三大特性的来由与特点。
面向对象的思想来自现实生活,符合我们人类的一般思维模式,所以三大特性其实也来自我们的日常生活。也非常的切合日常的生存使用模式。
我们现实生活中的一切复杂工具其实都是被封装起来的,在工厂生产线上就已经被封装了起来。比如电视,我们只需要通电,打开,选台,观看,关闭,断电就行,核心其实就一个功能——看电视节目。可是这一个功能却需要几百种技术,几十个功能,四五个重要木块的共同协作才能完成。
而我们需要知道吗。不需要的,于是这些功能以及木块都被外壳封闭了起来。其重要作用就是保护这些设备。而留给我们的就是一些主要的一选台为主的调节按钮。这些以及里面的一些连接线就是内外沟通的渠道。
在封装里面的沟通渠道就是set/get方法。归根到底安全起到主要作用。
封装不仅仅针对属性,还有方法。
不仅如此,任何工厂每完成一个产品的制造都会有一个简单的封装。电视的零部件来自无数的厂家,每个厂家生产一个零部件基本上都会进行一个简单的封装。所以封装可以说是层层都有,封装套封装,就好像一个集合套一个集合,永远没有尽头一样。我们的现实社会也是一样,家庭封装爸爸妈妈,然后是小区,街道城市,地区,省市,国家,州域,地球,太阳系等等无穷封装包涵下去。
这就是封装的来源。
而参数列表以及构造函数都是为了内外沟通存在的。
电视通常不仅仅要使用他,还想要拥有它,单单的封装就不足以应付。比如西方国家发明了电视,我们国家想要也制造出来电视,而不仅仅是买回来使用它,那么最好的办法就是学会制造电视的技术,引进生产电视的技术,改变生产管理模式。这也是一种继承,技术上的继承。即使这个过程复杂而艰难。代价重重,也不能阻碍我们继承这种技术的决心。因为这种继承是人类不断进步的的最好方式。
就说印刷术,从古代的誊写,到调版印刷术,到活字印刷术,到油蜡印刷术,到打印机等等,这一个个过程,其实就是一个个继承的过程。而且不单单是继承,还要在继承的基础上做些自己独有的改进,也正是这些点点滴滴的改进,从量变到质变,促进了技术的跟新换代。
而也正是这一个个继承,与继承之上的重写,存进了我们文明的而进步。
扯得这么远,只是因为面向对象的编程根本上是一种思想,只要我们从思想上理解了这一设计理念,才能更好的使用它,所以这里扯了很多概念性的动心。
转回多态。
正因为一个个的继承,特别是一个个的重写,导致子类的多种多样,导致了不同与父类的多种样式,百花齐放,才装点了多姿多态的社会。多态你也可以理解为个性。而不是流水线产品,也不是样板戏这些虽然经典但是无趣的社会。
这就是多态的含义,也是多态来源于封装与继承的基础的原因。

多态主要是方法的多态,以及返回类型的多态。
实际上仍然是数据类型的多态。来回处理数据的主要部分在于两个地方,一个是方法的参数列表另一个是返回值的位置。因为身处位置不同而出现了两者的区分,两种主要的多态应用。这两者都可以算是不同数据类型的多态。
所以只要理解了其中之一基本上就明白了另一个。
而多态的重点难点就是数据类型的不断上下转型,所以下面主要解释的就是向上转型,向下转型。

向上转型,向下转型,平型转型。
public class Docter {
public void cure(Pet pet){
if (pet.getHealth()<60) {
pet.toHostipal();
pet.setHealth(60);
}
看病的方法里面的而参数列表,有Pet类型,就可以调用Pet里面的属性。不用new。很神奇。而且因为Pet是父类,所以可以传递所有子类的参数。调用子类的方法。更加神奇。是不是。

前面我们说参数列表有说道,为了处理各种类型的数据,可以设置多种参数列表的重载方法,形成一整套数据处理的方案。为的就是能够处理足够多类型的数据。可是此处只需要用父类类型一个参数就能传递所有的子类类型的数据。是不是更加神奇。这就是多态的一大用处。

这就是将父类作为形参,形式上的参数。

编译时类型与运行时类型:

但是如果我们将Pet类型降低,降为Dog类型。
public void cure(Dog pet){…………}
那么只能传递Dog类型的参数,调用它的方法,其他的动物子类比如Bird的参数就不能传递,只能强制装行为Dog类型的才能传递。但是编译不报错,运行时却会报错。
这也算是平行转型了。到了这里就大概明白为何要向上转型了。因为此处的方法限制传递的参数为Pet类型,所以首先要将所有的参数转化为Pet类型才能传递。
Pet pet=new Dog();
这个很像数据类型转换。或者根本就是一个原理,毕竟都是在进行数据处理。如下;
double a=11*2.5;
这里就是讲new的Dog对象转型为Pet类型。才能传参。但是实质还是Dog类型的数据。所以运行的时候调用的其实还是Dog的属性与方法。这里的Pet类型只是为了一步到位可以传递所有的子类参数与方法。
举一个不恰当的例子,公路的级别越高,能运行的车辆类型与数量越高,但是实质上行驶的车辆是自行车还是自行车,是汽车还是汽车。不会因为公路等级的增加而变化。
这就是编译时类型与运行时类型。
编译时类型有声明该变量的使用类型决定,一般都是父类的高等级类型。
运行时类型有实际付给该变量的对象决定。一般都是子类的低等级类型。
编译类型就好像形式参数,运势型类型就好像实际参数。

这个时候同一个声明的类型,就能通过调用不同子类的参数与方法,实现子类的重写方法。
这样一解释我们是不是发现这一理解跟多态的定义很相似啊。

多态:同一个引用类型(声明类型),使用不同的实例(实质参数)执行不同的操作(实质的方法。)

自动类型转换与强制类型装换:
不会因为等级的增高而变化,却会因为等级的降低而变化,比如高速公路,堵塞,为了赶路只能走一截乡间马路绕路而走。那么跑车就不能行驶了,除非事先对其底盘等等车体进行改装,不然磕磕碰碰,回厂返修成为了必然。
这样一来,低级车辆行驶在高级公路上只会更舒服,不会有损耗,但是高等级的车辆行驶在低等级的道路上必然会有损耗,而且还必须进行相应的改装。嘿嘿,越是低级的工具越能适应高级的道路,凡是是高级的工具反而很难使用于低级的公路。这样一来我们的自行车11路反而是最实用的交通工具了。嘿嘿。
这就是自动类型转换无损耗与强制类型装换有损耗的原因吧。如下:
double a=112.5;//=27.7
int b=(int)(11
2.5);=27
自动类型转换没有数据损耗,但是强制类型转化就有损耗。损耗了0.5.
不好意思举得例子不恰当。

向上转型和向下转型:
我们可以调用父类子类都有的属性与方法。但是却不能调用子类所独有的方法。比如Dog类中的run方法。如下:
public void run() {
System.out.println("小狗能跑");
}
因为已经经过向上转型变为了父类的类型,名义上好似是在用父类的对象调用一切,可以调用与父类有关系的子类的方法,但是子类自己的独有方法确实属于子类独有,与父类没有关系,中间差了一个连接。
就好似子类的私人物品没有也没必要在父类哪里登记造册。或者说是本来就不能调用私有的方法。因为父子类重写的方法不能降低访问权限,所以可以说仍然是公有的方法。这才是能够调用的另一个原因。
这个时候可以重新用我们的万金油犯法调用。
Dog dog=new Dog();
代码变为如下:
public void cure(Pet pet){
if (pet.getHealth()<60) {
pet.toHostipal();
pet.setHealth(60);
Dog dog=new Dog();
dog.run();
}
确实能够调用。
而实际上我们都知道此时参数列表传递进来的pet本质上就是一个Dog类型的参数。前面已经new过了,这里应该没有在new的重复必要了吧。那么我们将其两相结合。进行一下精简:
Dog dog=(Dog)pet;
对其进行强制转换。其实质不过是转回来而已。假如你以为换了一套马甲就可以换成另一个人,向下转型强制转换为小鸟类
Bird bird=(Bird )pet。
那你就错了。即使编译器不报错。但是运行时就会报错,转换类型的错误。进错房间了。如上面平行转型报错的结果一样。你一个披着小鸟外衣的小狗还能调用小鸟的私有财产不成。只能如下:
public void cure(Pet pet){
if (pet.getHealth()<60) {
pet.toHostipal();
pet.setHealth(60);
Dog dog=(Dog)pet;
dog.run();
}
嘿嘿,效果一样,这就是向下转型。即使你把dog改为bird。
Dog bird=(Dog)pet;
效果还是一样。这样的结果在测试的时候new什么类型的对象的时候就决定了。
其实不过是为了工作需要出外办公换了一套马甲,回家了自然要换回来的一样。就好像明星为了工作化浓妆(向上转型),工作完了,卸妆回家(向下转型)。能用的还是只有自己的东西。没可能范爷的替身出神入化的打扮成一个范爷的妆容就可以使用李晨的东西了。
向上转型,向下转型,转了一圈又转了回来。完整的代码如下:
Pet pet=new Dog();//子类到父类的向上转型。
pet.toHospital();//Pet类型的变量调用Dog类重写方法。

Dog dog=(Dog)pet;//父类装换为子类的强制类型转换,向下转型。
Bird bird=(Bird )pet;//这个就是类型转换报错。

不过如果范爷的替身跟范爷真的好想一个模子出来的话,李晨未必认得,不管真认不出来还是不愿意认出来。嘿咻嘿咻。
这时候就有问题了。所以必须有一道检验的手续,检验真假明星,要不然我也去整一个范爷的容貌,出席一个活动,挣个几百万,在整回来。虽然我是男的。稍微困难了一些。嘿嘿。
所以检验的手续就成为了必不可少的。这就是instanceof运算符。
修建这个检验手段的方法也就是语法就是:
<引用变量> instanceof<类接口/接口名称>
比如:
if(pet instanceof Dog ){……}else if(pet instanceof Bird){……}
方法体就不写了。
当然这个判断必须在使用之前进行判断,不然都滚床单了,还判断个屁啊。

其实我们一直在医生类里面打转,进行修改。而一般这样的类算是封装起来了。一般不对其进行修改。原来的代码如下:
public void cure(Pet pet){

    if (pet.getHealth()<60) {pet.toHostipal();pet.setHealth(60);}}

已经完成了自己的看病方法,可以封装起来。
至于到底传了写什么参数,类型怎么转换,完全应该放到外面进行,比如测试类里面。
这样的好处是可以不用管向上向下转型了,就是向上转型也容易理解一些。当然前面那样做不过是为了讲解清楚而已。
知道了原理,我们还是用简单清晰的办法来解决问题的好。
就比如我们在测试类里面这样写:
Dog dog=new Dog();
bird bird=new bird();

Docter doctoer=new Doctoer();
docter.cure(bird);
docter.cure(dog);
将中间的转型过程完全交给系统,让他自己默默地完成就行。我们就不用参与这么基层的工作了。这也算封装的好处。将方法封装起来,我们只需要拿来用就行,简单省事多了。
从这里更能见识到父类作为参数类型处理数据的伟大。和前面的一整套重载方法配合起来,简直能处理绝大多数数据。包含基本类型数据,引用类型数据,自定义类型数据。是不是很酷。

如果父类中没有这个方法,则说明这是子类独有的方法,则不能调用。如果父类有而子类没有,则调用的是父类的方法。在这里,好像也蕴含了方法的重写,不过不是重写,而是重新输出。子类的方法覆盖了父类的方法。这个还真没有找到测试的办法来验证是否如此。

转载于:https://my.oschina.net/weiweiblog/blog/690358

java 封装 继承和多态相关推荐

  1. Java:继承和多态实验(以狗,猫,青蛙为)

    Java:继承和多态实验(以狗,猫,青蛙为例) 问题描述: 问题分析: 难点分析: 类关系图: 阶段划分: 第一阶段: 第二阶段: 第三阶段: 运行效果: 总结: 问题描述: 狗生活在陆地上(是一种陆 ...

  2. java多态ppt_轻松学Java之继承与多态PPT课件.pptx

    轻松学Java之继承与多态PPT课件.pptx 第8章 继承与多态,在前面我们已经了解了类的基本使用方法.对于面向对象的程序而言,它的精华在于类的继承可以以既有的类为基础,进而派生出新的类.通过这种方 ...

  3. Java利用继承和多态来求矩形、正方形和圆形的面积与周长

    题目 Java利用继承和多态来求矩形.正方形和圆形的面积与周长 import static java.lang.Math.PI;/*** @Author Ziph* @date 2020/2/20* ...

  4. java 封装 继承 堕胎_JAVA封装、继承、多态

    封装 1.概念: 将类的某些信息隐藏在类的内部,不允许外部程序访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.好处: a.只能通过规定的方法访问数据 b.隐藏类的实例细节,方便修改和实 ...

  5. 细品java封装继承多态

    目录: 1.封装 2.继承 3.多态 1.封装 封装的作用:封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问.但是如果一个类没 ...

  6. java封装继承多态的理解_用最傻瓜式的方法理解Java中的封装、继承和多态

    说到java中面向对象的封装.继承和多态,很多人会说这么简单这么入门的东西一直讲干嘛,虽然是基础,但是我们要明白,所有东西都是要在基础上发展的,没有基础就去学其他的,那么你肯定是很容易失败的,那么应该 ...

  7. java封装 继承 多态_Java 封装、继承、多态

    Java 封装.继承.多态 1.封装: 封装的理解: 将类的某些信息隐藏在类的内部,不允许外部程序直接访问,并通过该类提供的方法来实现对隐藏信息的操作和访问.(简单的说就是隐藏对象的信息,留出访问的接 ...

  8. Java回顾 封装 继承和多态

    封装 什么是封装 封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式. 封装时的权限控制符区别如下: 封装的意义 对于封装而言,一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其他对象 ...

  9. java 封装 继承 堕胎_Java的继承、封装和多态

    一.继承 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为. 继承的特性 子类拥有父类非 private 的属性.方法. ...

最新文章

  1. 探究位置误差对单目3D目标检测影响
  2. aix 查看目前java进程_问一个 AIX 的命令 ps -ef|grep java
  3. Tar打包、压缩与解压缩到指定目录的方法
  4. 类似flashget的浮动窗口的实现
  5. AngularJS与Angular的区别
  6. Unsupported major.minor version (jdk版本错误)解决方案办法
  7. 服务器2003系统U盘安装方法,u盘winpe下安装windows server 2003详细教程
  8. 数据采集之登录那些事
  9. vscode配置opencv
  10. 搜狗拼音输入法 V9.1.0.2589 最新去广告精简优化版
  11. iFixit 拆解 2014 款 Mac mini拆机教程, 内存确认不能更换.
  12. ysoserial exploit/JRMPClient原理剖析
  13. Exception: ROM is missing for xxxx, see https://github.com/openai/atari-py 强化学习安装Atari环境时ROMS丢失解决办法
  14. 无理数存在性的几何证明
  15. sql 一张表递归_查看我的递归视觉指南(因为一张图片价值1,000字)
  16. 入门文献复现——Murphy C K——Combining belief functions when evidence conflicts
  17. unityShader入门了解
  18. Thinkphp5威客任务平台网站源码
  19. 147 completion机制基本概念
  20. 信息设计软件+信息图表设计软件介绍

热门文章

  1. 51单片机学习笔记(郭天祥版)(4)——练习、动态扫描、练习、数码管消影...
  2. 由防止表单重复提交引发的一系列问题--servletRequest的复制、body值的获取
  3. BZOJ1801: [Ahoi2009]chess 中国象棋
  4. Android 打造自己的个性化应用(四):仿墨迹天气实现--自定义扩展名的zip格式的皮肤...
  5. ExtJs组件之间的相互访问,访问机制
  6. 过滤掉空格( /r/n) 和html标签
  7. 换个视角看中台的对与错
  8. PMCAFF专访:搜狗effevo,这一次我们想连接“人”
  9. python基本库系列一:Request
  10. Latex 数学公式使用入门