资源描述
Java编程思想,第七章:多态,面向对象的设计,数据抽象化、封装继承多态,多态,接口与实现分离:实现了“是什么”与“怎样做”两个模块的分离代码的组织以及可读性均能获得改善能创建易于扩充的程序多态性涉及对“类型”的分解:通过继承可将一个对象当作它自己的类型或者它自己的基础类型对待只需一段代码,即可对所有不同的类型(相同的基础类型中衍生出来的)进行同样的处理相似类型之间的区分是通过“函数的行为差异”实现而这些函数都可通过基础类函数唤起,向上转型,将某个objectreference视为一个指向基类的reference,classA,classB,/:Music.java(p220)/Inheritance,/Windobjectsareinstruments/becausetheyhavethesameinterface:classWindextendsInstrument/Redefineinterfacemethod:publicvoidplay(Noten)System.out.println(Wind.play();publicclassMusicpublicstaticvoidtune(Instrumenti)/.i.play(Note.middleC);publicstaticvoidmain(Stringargs)Windflute=newWind();tune(flute);/Upcasting/:Ans:Wind.play(),将对象的类型忘掉:为了扩充,/:c07:music2:Music2.java(p221)classNoteprivateintvalue;privateNote(intval)value=val;publicstaticfinalNoteMIDDLE_C=newNote(0),C_SHARP=newNote(1),B_FLAT=newNote(2);/Etc.classInstrumentpublicvoidplay(Noten)System.out.println(Instrument.play();classWindextendsInstrumentpublicvoidplay(Noten)System.out.println(Wind.play();,classStringedextendsInstrumentpublicvoidplay(Noten)System.out.println(Stringed.play();classBrassextendsInstrumentpublicvoidplay(Noten)System.out.println(Brass.play();,publicclassMusic2publicstaticvoidtune(Windi)i.play(Note.MIDDLE_C);publicstaticvoidtune(Stringedi)i.play(Note.MIDDLE_C);publicstaticvoidtune(Brassi)i.play(Note.MIDDLE_C);publicstaticvoidmain(Stringargs)Windflute=newWind();Stringedviolin=newStringed();BrassfrenchHorn=newBrass();tune(flute);/Noupcasting,oveloadingtune(violin);tune(frenchHorn);/:,Ans:Wind.playStringed.playBrass.play,函数调用绑定,Binding:建立函数调用和函数体的关联C:先期绑定Java:后期绑定(除声明为final外)动态绑定,执行期绑定final关键字:关闭动态绑定,产生正确的行为,调用baseclass中的函数所有的derivedclasses会产生正确的行为将一条消息发给一个对象,让对象自行判断要做什么事情,Shape及其子类,后期绑定:扩展性,/:Shapes.java(p225)/PolymorphisminJavaclassShapevoiddraw()voiderase()classCircleextendsShapevoiddraw()System.out.println(Circle.draw();voiderase()System.out.println(Circle.erase();,classSquareextendsShapevoiddraw()System.out.println(Square.draw();voiderase()System.out.println(Square.erase();classTriangleextendsShapevoiddraw()System.out.println(Triangle.draw();voiderase()System.out.println(Triangle.erase();,publicclassShapespublicstaticShaperandShape()switch(int)(Math.random()*3)default:/Toquietthecompilercase0:returnnewCircle();case1:returnnewSquare();case2:returnnewTriangle();publicstaticvoidmain(Stringargs)Shapes=newShape9;/Fillupthearraywithshapes:for(inti=0;is.length;i+)si=randShape();/Makepolymorphicmethodcalls:for(inti=0;is.length;i+)si.draw();/:,Ans:(答案不唯一)Circle.drawSquare.drawTriangle.drawTriangle.drawSquare.drawSquare.drawSquare.drawCircle.drawSquare.draw,扩充性,后来可加入更多的型别在围绕tune()方法的其他所有代码都发生变化的同时,tune()方法却丝毫不受它们的影响,依然正常工作。这正是利用多形性希望达到的目标。允许程序员“将发生改变的东西同没有发生改变的东西区分开”,Instrument及其子类,/:Music3.java(p227)/Anextensibleprogramimportjava.util.*;classInstrumentpublicvoidplay()System.out.println(Instrument.play();publicStringwhat()returnInstrument;publicvoidadjust()classWindextendsInstrumentpublicvoidplay()System.out.println(Wind.play();publicStringwhat()returnWind;publicvoidadjust(),classPercussionextendsInstrumentpublicvoidplay()System.out.println(Percussion.play();publicStringwhat()returnPercussion;publicvoidadjust()classStringedextendsInstrumentpublicvoidplay()System.out.println(Stringed.play();publicStringwhat()returnStringed;publicvoidadjust()classBrassextendsWindpublicvoidplay()System.out.println(Brass.play();publicvoidadjust()System.out.println(Brass.adjust();,classWoodwindextendsWindpublicvoidplay()System.out.println(Woodwind.play();publicStringwhat()returnWoodwind;publicclassMusic/Doesntcareabouttype,sonewtypes/addedtothesystemstillworkright:staticvoidtune(Instrumenti)/.i.play();staticvoidtuneAll(Instrumente)for(inti=0;ie.length;i+)tune(ei);,publicstaticvoidmain(Stringargs)Instrumentorchestra=newInstrument5;inti=0;/Upcastingduringadditiontothearray:orchestrai+=newWind();orchestrai+=newPercussion();orchestrai+=newStringed();orchestrai+=newBrass();orchestrai+=newWoodwind();tuneAll(orchestra);/:,Ans:Wind.play()Percussion.play()Stringed.play()Brass.play()Woodwind.play(),覆写(重写)(overriding),在子类中,具有与父类相同名字、相同参数表和相同返回值的方法子类通过重写把父类的状态和行为改变为自身的状态和行为子类通过super实现对父类成员的访问Java通过方法重写来实现多态,覆写vs.重载,/:c07:WindError.java重载(p229)/Accidentallychangingtheinterface.classNoteXpublicstaticfinalintMIDDLE_C=0,C_SHARP=1,C_FLAT=2;classInstrumentXpublicvoidplay(intNoteX)System.out.println(InstrumentX.play();,classWindXextendsInstrumentX/OOPS!Changesthemethodinterface:publicvoidplay(NoteXn)System.out.println(WindX.play(NoteXn);publicclassWindErrorpublicstaticvoidtune(InstrumentXi)/.i.play(NoteX.MIDDLE_C);publicstaticvoidmain(Stringargs)WindXflute=newWindX();tune(flute);/Notthedesiredbehavior!/:,Ans:InstumentX.play,Abstractclasses(抽象类)和methods(抽象函数),抽象函数前面使用“abstract”关键字一种不完全的函数含有抽象函数的类为抽象类,前面必须使用Abstract修饰,即Abstractclass,abstractvoidf();,Instrument及其子类,(参阅p232Music4.java),构造函数调用顺序,1.调用基类构造函数:反复递归,直到最后一层子类之前2.依次将各个数据成员初始化3.调用子类构造函数本身,Sandwich层次结构,Meal,Bread,Cheese,Lettuce,Lunch,PortableLunch,Sandwich,构造函数调用顺序,/:Sandwich.java(p234)/OrderofconstructorcallsclassMealMeal()System.out.println(Meal();classBreadBread()System.out.println(Bread();classCheeseCheese()System.out.println(Cheese();,classLettuceLettuce()System.out.println(Lettuce();classLunchextendsMealLunch()System.out.println(Lunch();classPortableLunchextendsLunchPortableLunch()System.out.println(PortableLunch();,classSandwichextendsPortableLunchBreadb=newBread();Cheesec=newCheese();Lettucel=newLettuce();Sandwich()System.out.println(Sandwich();publicstaticvoidmain(Stringargs)newSandwich();/:,Ans:Meal()Lunch()PortableLunch()Bread()CheeseLettuceSandwhch,将继承运用于设计,当我们以一个现有类为基础建立一个新类时,如首先选择继承,会使情况变得异常复杂。使用继承时要谨慎准则:使用继承表达行为上的差异,以数据成员表达状态上的变化组合手法较灵活,弹性大,/:Transmogrify.java(p241)/Dynamicallychangingthebehaviorof/anobjectviacomposition.abstractclassActorabstractvoidact();classHappyActorextendsActorpublicvoidact()System.out.println(HappyActor);classSadActorextendsActorpublicvoidact()System.out.println(SadActor);,classStageActora=newHappyActor();voidchange()a=newSadActor();voidgo()a.act();publicclassTransmogrifypublicstaticvoidmain(Stringargs)Stages=newStage();s.go();/PrintsHappyActors.change();s.go();/PrintsSadActor/:,Ans:HappyActorSadActor,纯粹继承p242图,只加以覆写“is-a”(是一种)关系纯取代,如下面这张图所示:,扩充p243图,“is-like-a”(像是一个)关系关键字“extends”似乎也在鼓励这么做,向下转型与执行期型别辨识,RTTI:run-timetypeidentification向上转型绝对安全向下转型可能会不安全,P244图,/:c07:RTTI.java(p244)/DowncastingclassUsefulpublicvoidf()publicvoidg()classMoreUsefulextendsUsefulpublicvoidf()publicvoidg()publicvoidu()publicvoidv()publicvoidw(),publicclassRTTIpublicstaticvoidmain(Stringargs)Usefulx=newUseful(),newMoreUseful();x0.f();x1.g();/Compile-time:methodnotfoundinUseful:/!x1.u();(MoreUseful)x1).u();/Downcast/RTTI(MoreUseful)x0).u();/Exceptionthrown/:Ans:编译通过,运行时产生ClassCastException错误,执行期型别,使客户端得以发现对象的型别ClassCastException第12章,摘要,多态:不同的形式多态是后期绑定发现classes的共同性及彼此关系可扩充性是关键,作业,阅读第7章第7章:2,9,14,谢谢,
展开阅读全文