




已阅读5页,还剩67页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第八章多态,多态向上转型和动态绑定构造器和多态,一、复习,面向对象的三大基本特征抽象与封装、继承、多态,一、复习,1、抽象与封装抽象:抓住事物的主要特征静态特征数据,动态特征方法,一、复习,封装:将这些数据和方法封装在一起,形成类通过封装和访问控制,可以对类中的数据成员和成员函数起到保护作用接口与实现的第一次分离,一、复习,2、继承继承的作用通过继承,可以以现有类为基础,派生出新类,达到代码重用的目的,一、复习,继承的本质将从同一基类导出的多种类型视为同一类型来处理,而同一份代码就可以毫无区别地运行在这些不同的类型之上了,数据成员,成员函数,一、复习,3、多态(polymorphism)多态的作用多态是面向对象最核心的机制,多态使程序的可扩展性达到了极至,一、复习,多态的本质多态方法调用允许一种类型表现出与其它相似类型之间的区别,只要它们都是从同一基类导出来的,一、复习,多态的典例:Shape基类和它的若干个派生类分析其draw方法,Circle(圆形),Square(方形),Triangle(三角形),数据成员,成员函数(接口),继承与多态的重要区别继承侧重于:父类的成员将原封不动的遗传给子类多态侧重于:父类的成员将会在子类中被覆盖,即父类的成员在子类中具有各种各样的形态,一、复习,多态的概念概念之一:多态包括两种情况:重载与覆盖,一、复习,概念之二:多态,也称为动态绑定,指的是在执行期间(而非编译期间)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法,归纳与分析:非常重要,彻底理解多态的关键当你调用父类里面被覆盖方法的时候,实际当中new的是哪个对象,就调用当前这个对象(子类对象)的与之相关的覆盖方法使用多态的三个条件:继承、覆盖与向上转型典例:使用上面的Shape及其子类作出初步分析,二、再论向上转型,1、以乐器作为典例开始分析(P148)在第七章例题的基础上,再增加一个Note类(乐符类),publicenumNote/枚举类型MIDDL_C,C_SHARP,B_FLAT;/Sharp(升半音),Flat(降半音)classInstrument/乐器publicvoidplay(Noten)/演奏/被覆盖方法print(“Instrument.play()”);,publicclassWindextendsInstrument/音乐分为管乐、弦乐、鼓乐等等publicvoidplay(Noten)/Redefineinterfacemethod/覆盖基类继承下来的方法/相关的覆盖方法print(“Wind.play()”+n);,publicclassMusicpublicstaticvoidtune(Instrumenti)i.play(Note.MIDDLE_C);/调音publicstaticvoidmain(Stringargs)Windflute=newWind();/长笛tune(flute);/向上转型,二、再论向上转型,2、第一个问题:为什么不让tune()方法直接接受一个Wind引用作为自己的参数,这样不是更加直观吗?,即:为什么不将程序改写为这样?publicclassMusicpublicstaticvoidtune(Windi)i.play(Note.MIDDLE_C);/调音publicstaticvoidmain(Stringargs)Windflute=newWind();/长笛tune(flute);/非向上转型,分析:如果Instrument类只有一个子类,确实应该这样改写,这时没有使用向上转型的丝毫理由问题是:一个基类绝非只有一个子类,而如果不采用向上转型,我们的代码就存在着很多的隐患和缺陷(通过下面例子可以看到这一点),publicenumNote/枚举类型MIDDL_C,C_SHARP,B_FLAT;/Sharp(升半音),Flat(降半音)classInstrumentpublicvoidplay(Noten)/演奏print(“Instrument.play()”);,publicclassWindextendsInstrument/音乐分为管乐、弦乐、鼓乐等等publicvoidplay(Noten)/Redefineinterfacemethod/覆盖基类继承下来的方法print(“Wind.play()”+n);,/增加Stringed(弦乐)类和Brass(铜管乐)类publicclassStringedextendsInstrumentpublicvoidplay(Noten)print(“Stringed.play()”+n);publicclassBrassextendsInstrumentpublicvoidplay(Noten)print(“Brass.play()”+n);,publicclassMusicpublicstaticvoidtune(Windi)i.play(Note.MIDDLE_C);publicstaticvoidtune(Stringedi)i.play(Note.MIDDLE_C);publicstaticvoidtune(Brassi)i.play(Note.MIDDLE_C);,publicstaticvoidmain(Stringargs)Windflute=newWind();tune(flute);/长笛Stringedviolin=newStringed();tune(violin);/小提琴BrassfrenchHorn=newBrass();tune(frenchHorn);/法国号/均未采用向上转型,我们来分析这样做的缺点:1、程序变得繁琐而复杂每增加一个新的子类,这些方法必须重新写一遍2、程序存在漏洞的可能如果我们忘记了重载某个方法,编译器不会提醒下面我们采用向上转型来改写这段代码,publicenumNote/枚举类型MIDDL_C,C_SHARP,B_FLAT;/Sharp(升半音),Flat(降半音)classInstrumentpublicvoidplay(Noten)/演奏print(“Instrument.play()”);,publicclassWindextendsInstrument/音乐分为管乐、弦乐、鼓乐等等publicvoidplay(Noten)/Redefineinterfacemethod/覆盖基类继承下来的方法print(“Wind.play()”+n);,/增加Stringed(弦乐)类和Brass(铜管乐)类publicclassStringedextendsInstrumentpublicvoidplay(Noten)print(“Stringed.play()”+n);publicclassBrassextendsInstrumentpublicvoidplay(Noten)print(“Brass.play()”+n);,publicclassMusicpublicstaticvoidtune(Instrumenti)i.play(Note.MIDDLE_C);/调音publicstaticvoidmain(Stringargs)Windflute=newWind();tune(flute);/长笛Stringedviolin=newStringed();tune(violin);/小提琴.,归纳:多态的作用和优点可扩展性那些操纵基类接口的方法不需要任何改动就可以应用于新类分析:增加一个新类时,我们需要做哪些工作?,归纳:多态的作用和优点多态是将改变的事物与未改变的事物分离开来的重要技术分析:我们对tune()方法所做的任何修改,不会对程序中其他不应受到影响的部分产生破坏,二、再论向上转型,3、第二个问题:还有一系列更为复杂的疑问需要我们深入分析,归纳当完成转型之后,i.play()调用的是父类的play方法还是子类的play方法?更进一步,是哪个子类的play方法?为什么正好是我们所期望的输出结果?编译器是怎么知道的?,三、绑定,1、绑定(Banding)的概念将一个方法调用和一个方法主体关联起来的过程称为绑定,三、绑定,2、绑定(Banding)的分类静态绑定(前期绑定,编译时绑定)在运行前进行绑定动态绑定(后期绑定、运行时绑定)在运行的时候根据对象的类型进行绑定,三、绑定,3、典例分析我们再来分析一个非常经典的例子利用图形分析清楚,classProcessor/字符处理器publicvoida()System.out.println(“Processor.a()”);publicvoidb()System.out.println(“Processor.b()”);,classUpcaseextendsProcessorpublicvoidb()/实现对父类方法的覆盖System.out.println(“Upcase.b()”);publicvoidc()System.out.println(“Upcase.c()”);,classApplypublicstaticvoidmain(Stringargs)/向上转型Processorpro=newUpcase();pro.a();/实际调用的是Processor.a()pro.b();/实际调用的是Upcase.b()pro.c();/编译错误,向上转型的归纳:基父类实例=new子类();向上转型时,实例可以调用父类中所有特有的方法(未在子类中覆盖的方法)实例可以调用子类中覆盖父类的方法(即多态)但是不可以调用子类中特有的方法(即父类中没有的方法),三、绑定,4、注意:只有普通的方法调用可以是动态绑定的,域与静态方法不存在动态绑定任何域的解析都是在编译期间进行的静态方法是类的方法(不存在与对象的绑定),四、构造器和多态,1、构造器的调用顺序(复习)构造器的调用原则调用基类构造器,这个步骤会不断反复递归下去,递归的确切含义如下:首先是不断上溯,一直到这个层次的根调用基类构造器然后调转方向不断下溯首先是下一层的派生类,然后是再下一层的派生类,一直到最底层的派生类,为什么首先调用基类的构造器?只有基类的构造器才具有恰当的知识和权限来对自己的元素进行初始化保证在进入导出类的构造器时,在基类可供我们访问的成员都已得到初始化,四、构造器和多态,初始化的基本原则在下溯并调用派生类构造器的过程中,要遵守初始化的基本原则包括第一基本原则和第二基本原则,典例分析:P158classMeal/一餐(粗粮)Meal()print(“Meal()”);classBread/面包Bread()print(“Bread()”);classCheese/奶酪Cheese()print(“Cheese()”);,classLettuce/莴苣Lettuce()print(“Lettuce()”);classLunchextendsMeal/午餐Lunch()print(“Lunch()”);classPortablelunchextendsLunch/便携式Portablelunch()print(“Portablelunch()”);,publicclassSandwichextendsPortablelunchprivateBreadb=newBread();privateCheesec=newCheese();privateLettucel=newLettuce();Sandwich()print(“Sandwich()”);publicstaticvoidmain(Stringargs)newSandwich();,四、构造器和多态,2、继承与清理(复习)关键:与初始化顺序相反典例分析:P159160,四、构造器和多态,3、构造器内部的多态方法的行为首先,我们知道:在一般方法的内部,动态绑定的调用是在运行时才决定的因为编译器无法知道:方法所要绑定的对象是基类对象还是派生类对象,方法A()/这是所谓的一般方法.方法B().;/这是发生动态绑定之处.注意:我们这里讨论的是方法B无法知道它所要绑定的对象到底是谁?,四、构造器和多态,如果将这种思路推广到:调用构造器内部的一个动态绑定方法,那么会发生什么情况?结果难以预料,因为被覆盖的方法在对象被完全构造之前就会被调用,classGlyph/雕像,象形文字voiddraw()print(“Glyph.draw()”);Glyph()print(“Glyph()beforedraw()”);draw();print(“Glyph()afterdraw()”);,classRoundGlyphextendsGlyphprivateintradius=1;RoundGlyph(intr)radius=r;print(“RoundGlyph.draw(),radius=”+radius);voiddraw()/发生覆盖print(“RoundGlyph.draw(),radius=”+radius);,/测试程序publicclassPolyConstructorspublicstaticvoidmain(Stringargs)newRoundGlyph(5);/该类为主类,注意其两个明显特征,分析其执行过程:主类的这条语句将被首先执行:newRoundGlyph(5)根据构造器的调用原则,编译器将不断上溯直至该类的根,然后开始调用其基类构造器,分析其执行过程:在调用基类构造器Glyph()过程中,将会发生draw()方法的调用根据动态绑定的理论,我们知道,这时候将会调用派生类的draw()方法因为new的是RoundGlyph而不是Glyph,分析其执行过程:这时我们将看到一个悲剧:派生类的draw()方法所涉及的数据成员radius还来不及初始化掉进了一个两难境地的陷阱(派生类初始化依赖于基类,而基类却又依赖于派生类的初始化),归纳:前面讲述的初始化顺序并不十分完整初始化的实际过程应该首先执行:将分配给对象的存储空间初始化为二进制的零然后再是:初始化基本原则+构造器调用原则,五、协变返回类型,1、Java1.4及以前版本子类方法如果要覆盖超类的某个方法,必须具有完全相同的方法签名,包括返回值也必须完全一样,五、协变返回类型,2、JavaSE5以后的版本放宽了这一限制只要子类方法与超类方法具有相同的方法签名,或者子类方法的返回值是超类方法的子类型,就可以覆盖,classGrain/谷类publicStringtoString()return“Grain”;classWhea
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 年度绩效考核及薪资增长证明(7篇)
- 读小王子的心灵触动读后感话题展开(12篇)
- 银符考试试题及答案
- 六一全套活动方案
- 六一卤味店活动方案
- 六一商场游园活动方案
- 六一官方活动方案
- 六一操场活动策划方案
- 医学导论考试试题及答案
- 六一法治活动方案
- 习近平总书记关于应急管理的重要论述
- 2025年陕西省新高考语文试卷(含答案解析)
- 期末试卷(试题)(含答案)-2024-2025学年一年级下册数学北师大版
- 《编织美好》教学课件-2024-2025学年鲁教版(五四学制)(2024)初中美术六年级上册
- 2025年江西省高考物理真题
- 2025年《国际金融》课程标准
- 国际道路运输管理制度
- 客户拜访跟进管理制度
- 湘教版七年级数学下册期末考试卷(附答案和解析)
- 2025湖南长沙市轨道交通运营限公司招聘372人易考易错模拟试题(共500题)试卷后附参考答案
- 2025智联银行笔试题库及答案
评论
0/150
提交评论