java基础-多态-多态的理解及使用

一.多态的含义

在面向对象(OOP)的程序设计语言中,封装,继承,多态与数据抽象是其基本特征

在java语言中,

封装就是合并属性与行为来创建一种新的数据类型,

继承则是表明数据类型之间的某种关系(is-a或is-like-a),

多态则是表明这种关系在实际场景中的运用,即行为中的做什么和怎么做,

数据抽象则是想隐藏这种数据类型中的部分属性或是隐藏部分行为的实现细节,即你知道我可以做什么,不用知道我为什么要这样做。

举例来说:一只猫,它有体重,毛发颜色,寿命。它能吃饭,睡觉,并且它是一种动物,像是加菲猫品种。

封装:猫,即一种数据类型,体重,毛发颜色和寿命是它的属性,吃饭,睡觉是它的行为。

继承:动物本身也是一种数据类型,而猫就是一种动物(is-a),像是加菲猫品种(is-like-a)。

多态:猫可以做什么呢,它可以吃饭,也可以去睡觉(即做什么),吃饭的话是喂它吃鱼还是猫粮呢,要睡觉的话是白天睡还是晚上睡呢?(怎么做)

数据抽象:你不用关心它的寿命(什么时候会死),为什么要吃饭(不吃会死)和为什么要睡觉(不睡会死)。

所以,对应到类中来,多态就是把做什么和怎么做分开了,做什么是指调用哪个方法,怎么做是指方法的实现方案。分开了则是指调用哪个方法和怎么实现方法不在同一时间确定。

实质上,多态就是指父类引用指向子类对象,来产生不同的行为。这样做的好处是,可以消除类型之间的耦合(类与类之间的依赖程度)关系。看下面的例子:

看下输出:

Piano和Guitar类都继承自基类Instrument类,主类中playMusic方法,需要传递一个Instrument类型的参数,但是在main方法中,传递的却是Piano和Guitar类型的参数,而且程序能正常运行并且调用到正确的方法。

如果没有继承与多态,我们需要下图这样写,才能调用到3个类中不同的方法:

这样做的话,类Piano与Guitar便与主类UseOfPolyTest有了耦合,也就是依赖,如果不重载playMusic方法,那么就不能调用到他们各自的方法,继承和多态刚好可以消除这里的耦合,使代码冗余大大减少。

那么问题就来了:为什么可以通过继承与多态实现这样的功能呢?如果我们只写这样一个简单的方法,它仅接受基类作为参数,而不是那些特殊的导出类,编写的代码只是与基类打交道,会不会更好呢?事实上,这正是多态所允许的。那么这就要讨论多态的原理了。

二.多态的原理

上面的例子中,方法playMusic接受一个Instrument类型的对象,但是在调用的时候传递的却是它的子类对象的引用,主类在调用方法时好像忘记了对象的类型一样,这是奇怪之处,也是多态的体现。

这里有了一个疑问:方法playMusic(Instrument i)接受一个Instrument引用,那么在这种情况下,编译器怎么样才能知道这个Instrument引用指向的是Piano对象,而不是Guitar对象呢

答案是:编译器也无法得知,既然编译器不知道,那就肯定不是在编译期确定的。那么肯定就是在代码运行时确定的,具体表现就是确定方法调用与调用方法对象之间的关系,那么这个关系的确定就称为绑定。由于绑定动作发生在运行时,所以多态也称运行时绑定或者后期绑定,相比于静态的编译期,多态也称为动态绑定

动态绑定很抽象,我们不禁要问:JVM是如何绑定的呢?

关于这个问题,《Thinking In Java》里面作者是这么说的,如果一种语言想实现后期绑定,就必须具有某种机制,以便在运行时能判断对象的类型,从而调用恰当的方法。也就是说,编译器一直不知道对象的类型,但是方法调用机制能够找到正确的方法体,并加以调用。后期绑定机制随编程语言的不同而有所不同,但是只要想一下就会得知,不管怎么样都必须在对象中安置某种”类型信息“。

所以,动态绑定的过程可以理解为下面几个过程:

  • 当虚拟机创建Piano类对象的时候,会创建一个类的方法列表,同时包含父类的方法列表
  • 子类型Piano对象的引用向上转换成shape引用,确定引用与对象之间的关系
  • 3.虚拟机会找到参数引用实际指向的地址,也就是Instrument引用实际指向Piano对象,并查询对象的方法列表,如果在Piano对象中找到这个方法,就直接调用,否则查询父类Instrument中的方法并调用

注意步骤2中发生了类型转换。我们知道基本数据类型可以发生类型转换,如byte,short,char和int之间;那么引用类型之间也可以,但需要满足一定的条件(有继承关系)。那么这里发生的转换是从Piano对象转到Instrument对象,即从子类转换父类,是向上转换,

也称之为向上转型。向上转型的定义就是指把某个对象的引用视为对其基类型的引用的行为。

来验证一下动态绑定里面的第

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值