版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第七章多态与接口7.1多态7.2多态的支撑技术7.3多态实现7.4多态分析7.5接口本章小结
7.1多态
本章将要介绍的面向对象三大特征的最后一个特征——多态(Polymorphism),是面向对象编程中非常重要的技术,能增强程序的扩展性,提高程序的可维护性。如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不是面向对象的。多态是什么?多种形态?这样的回答是将问题还给提问者,任何意义,要理解多态,必须要清楚下列几个问题:
多态发生在什么地方?
多态是怎么发生的?
多态的支撑技术是什么?
多态有什么好处?
并且需要通过程序代码理解和掌握多态,否则就是纸上谈兵。
7.2多态的支撑技术
7.2.1向上转型1.向上转型子类继承父类,如Dog继承Animal,这是继承技术。有了继承才会有向上转型,即父类的引用变量指向子类的对象。这个在现实世界中很好理解:我们看到一只狗,可以说那只狗是一只动物,这种说法是没有问题的,这就是向上转型,其程序语句与内存示意图如图7-1所示。
图7-1向上转型内存示意图
2.向下转型
既然有向上转型,那向下转型呢?如果反过来,用子类的引用变量去指向父类的对象会如何呢?比如:
Dogdog=newAnimal("animal1",20); ×
这样的语句在程序编译阶段会直接报错,为什么呢?
现实世界中,不能随便看到一个动物就说该动物是一条狗,这样的说法是有问题的。当然也有成立的条件:这只动物本身就是一条狗。如果这只动物是别的动物,这个说法就是错误的。谁也不是魔法师,不能指着一条鱼说是狗,这只动物就变成了一条狗。
对于Dog类的引用变量dog而言,Dog类中定义了color成员变量,但是它现在指向的是一个Animal的对象,而在Animal类中并没有定义color成员,Animal对象在堆内存中自然也没有color这个成员,当dog对象想使用color成员的时候也会出错。
父类所有成员是子类所有成员的子集,所以父类的引用变量指向子类对象不会出现问题,只会出现一些成员被屏蔽不可见的情况;但是子类的引用变量指向父类对象,就会缺少一些成员,导致调用成员出错。在实际编程中,向下转型是使用强制类型转换来完成,但是应该谨慎使用,否则就会出现类型转换出错的异常。
7.2.2动态绑定
1.方法绑定
把一个方法与其主体关联起来叫做方法的绑定,方法的主体主要是类或对象。方法的绑定主要分为静态绑定、动态绑定(也可以称为前期绑定、后期绑定)。
2.静态绑定
在程序执行前方法已经与主体绑定,这是由编译器或其他连接程序来实现的,C语言的方法就是典型的静态绑定,在编译之前就可以通过阅读程序知道程序运行的结果。Java中也有静态绑定,如被final、static、private修饰的方法以及构造方法,其它方法都属于动态绑定。
3.动态绑定
动态绑定即方法与方法的主体在运行时才进行绑定。Java的大部分方法都属于动态绑定。Java中的动态绑定是由Java虚拟机来实现的,不用显式地声明;C++则不同,必须明确地声明某个方法具备后期绑定特性。
例如,程序语句“an.move();”中,move方法的调用主体是an,但是an只有在运行时才知道是什么动物,由于向上转型的存在,Animal、Fish、Dog、Bird这些类的对象都可以传递给an,不同类对象调用move()方法的表现是不同的,从这里就可以看出多态的特征了。
7.3多态实现
现在通过一个动物行为展示程序来说明多态的具体实现,该程序需要以下几个类:(1)动物类的父类Animal(也可以使用抽象的动物父类Animal2);(2)动物类的子类:Dog、Fish和Bird;(3)展示动物信息和行为的类:ShowMoving。这几个类及类关系的UML图如图7-2所示。
图7-2动物类UML图
程序结果:
7.4.1多态发生的地方上述动物展示的程序中,多态发生在showMove()方法上,该函数传入的参数对象为Animal2类型。在运行该方法时,由实际传入的具体对象来展示动物的信息及行为。如图7-3所示,可以看出多态的支撑技术以及其发生的地方。
7.4多态分析
图7-3多态的发生
7.4.2多态的作用
例如,对类ShowMoving来说,如果没有动态绑定,没有向上转型,那么该类要展示动物类,就会变成这样:
展示Fish类的showMove方法:
展示Dog类的showMove方法:
展示Bird类的showMove方法:
也就是说,ShowMoving类中会有很多showMove方法的重载,用以适应各种动物。当程序需要展示更多的动物类时,必须一是完成动物子类的编写;二是在ShowMoving类中重载对应的showMove()方法,而这些方法的方法体中都是相同的代码:“an.showInfo();”和“an.move();”,这样就会在该类中出现很多重复代码,并且难以维护。
有了多态,就可以发现在前面编写的程序中,不管增加多少个动物子类,对于ShowMoving类的showMove()方法都是不用改变的,而要展示更多的动物子类行为,只需完成动物子类的编写,生成对象交给showMove()方法,就可以展示出该动物子类对象的行为。通过方法showMove(Animal2animal),我们知道,只要是实现了抽象类Animal2的子类,都可以将自己的对象传入这个函数以展示自己的行为。多态消除了重复代码,程序的扩展性和维护性得到了增强。
7.5接口
7.5.1接口声明接口的定义和类的定义很相似,分为接口的声明和接口体,只是使用关键字interface代替了关键字class:
接口体中包含常量的声明(即使用final修饰的成员变量)和抽象方法两部分。由于全是抽象方法,所以abstract修饰符可以省略不写。接口体中所有的常量、所有的抽象方法的访问权限都是public(可以省略public修饰符)。下面我们通过一个实例将Animal2抽象类的两个方法抽取出来形成一个接口。
编译该接口,可以看到该接口源文件名还是Showable.java,编译之后的字节码文件还是Showable.class。
为什么接口的名字很多都加上了一个后缀able?这是大多数程序员的习惯,也算是一种命名风格,如定义的这个Showable接口,该接口名暗示我们:谁实现这个接口,谁就具有显示信息和展示行为的能力(也体现在两个方法的声明上)。
7.5.2实现接口
实现接口是指某个类通过继承的方式获得接口定义的方法,然后将接口中所有的抽象类的方法实现为非抽象方法。实现接口的类称为该接口的实现类。实现接口是使用implements关键字完成的:
从语法上说,一个类要实现一个接口就要将该接口的所有非抽象方法都实现(让方法具有方法体,如果方法体是空的{},则称为空实现);如果只是实现了部分抽象方法,按照抽象类的定义,该类就应该声明为一个抽象类。
一个类只能继承一个父类,但可以同时实现多个接口,如:
上述程序段的意思是:Dog类继承了Animal类,获得了Animal的成员,并且实现了Eatable和Sleepable,实现接口就具备了接口定义的能力,所以Dog类就可以eat,可以sleep了。
下面编写一个石头Stone类实现Showable接口。
Stone实现类实现接口Showable的UML图如图7-4所示。图7-4接口实现的UML图
7.5.3接口与多态
下面来看如图7-5所示三组关系,并思考这三组关系的演变。图7-5继承与实现
父类与子类是继承关系,抽象类与实现类实质上也是继承关系,接口是完全抽象类,所以接口与实现类也可以视为继承关系(实现类获得并重写了接口定义的成员方法),因此接口与实现类之间同样可以进行向上转型:接口类型的引用变量指向实现类的对象。
上面使用继承来实现多态时,ShowMoving类暗示:只要是动物类的子类都可以进入到该类的showMove()方法中展示自己的信息与行为,程序局限于只能对动物类的子类进行展示。而刚刚编写的Stone类从现实世界的观点来看,不应该是动物类的子类;从语法的角度来看,Java是单继承,Stone如果继承了其它类,就不能再继承动物类(Java并不支持多继承),那么,如何让Stone类也能够进入到ShowMoving类中展示自己的信息和行动呢?这就需要使用接口的方式实现多态。下面在以上继承实现多态的基础上进行改写。
(4)各个动物类的子类Fish、Dog、Bird均不变。
程序结果:
7.5.4面向接口编程
1.关于接口的几点认识
(1)接口的定义关心的是做什么,具体怎么做是由其实现类来完成的。
(2)接口体现的是一种规范,对于接口的实现者而言,接口规定了实现者必须向外提供哪些服务(方法对外提供服务与功能);对于接口的调用者而言,接口规定了调用者可以调用哪些方法,获得哪些服务,以及如何调用这些服务。
(3)当在一个程序中使用接口时,接口是多个模块间的耦合标准;当在多个应用程序之间使用接口时,接口是多个程序之间的通信标准。
(4)接口作为系统与外界交互的窗口,体现的是一种规范。从某种程度上来看,接口类似于整个系统的“总纲”或“框架”,它制定了系统各模块应该遵循的标准。
所以,接口体现的是一种规范和实现分离的设计理念,充分利用接口可以很好地降低程序各模块之间的耦合性,从而提高系统的可扩展性和可维护性。
2.面向接口编程(Interface-OrientedProgramming)
我们开始是使用继承来实现多态的,之后我们把要展示的两个方法showInfo()和move()抽取出来,放到Showable接口中,使用接口实现多态,然后发现程序的扩展性变得更强,具体的接口和类的结构如图7-6所示。
图7-6面向接口编程的UML图
如果能事先根据程序的需求预先定义好接口,由接口来定义规范搭建程序的框架,然后面向接口编程,编写具体的实现类,就会发现程序的扩展性和可维护性获得了增强,并且程序中的耦合性降低了,这是面向对象编程所希望做到的,也是面向接口编程的主要思想。
本章小结
1.实现多态程序需要的基本支撑技术包括继承、动态绑定、向上转型。2.动态绑定即Java的方法都是有主体的,只有当方法被调用的时候,才会和方法的主体进行绑定。3.向上转型即父类的引用变量可以指向子类的对象。4.使用继承来实现多态程序,程序的扩展性可以这样描述:只要是Animal类的子类,都能够进入到多态方法中展示自己的行为。
5.使用接口来实现多态程序,程序的扩展性可以这样描述:谁实现了相应的接口,谁就能进入到多态方法中展示自
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 二零二五版班班通设备与物联网结合合同2篇
- 二零二五年绿色生态住宅小区消防工程设计与施工合同3篇
- 二零二五版股份制企业股份自愿转让与投资者关系维护合同3篇
- 二零二五年度监理合同延期补充协议-责任划分与风险承担3篇
- 二零二五版中央空调清洗保养及能耗管理服务合同3篇
- 二零二五年度国有资产管理委托服务合同2篇
- 二零二五版股票质押担保合同范本编制与解析3篇
- 二零二五年度风力发电项目融资合同2篇
- 二零二五年美发师国际交流聘用合同2篇
- 二零二五年度酒店地毯翻新与维护服务合同范本3篇
- 五年级上册小数乘除竖式计算题200道及答案
- 2024年东南亚工业气瓶市场深度研究及预测报告
- 棉花良种选育与遗传育种
- 简易劳务承包合同范本
- SH/T 3078-2024 立式圆筒形料仓工程设计规范(正式版)
- 快递驿站承包协议书
- 基于视觉果蔬识别的称重系统设计
- 体育初中学生学情分析总结报告
- 部编版语文中考必背文言文7-9年级
- 农药合成研发项目流程
- 国家职业技术技能标准 4-04-04-02 网络与信息安全管理员(数据安全管理员)S 2024年版
评论
0/150
提交评论