第5章繼承接口型_第1頁
第5章繼承接口型_第2頁
第5章繼承接口型_第3頁
第5章繼承接口型_第4頁
第5章繼承接口型_第5頁
已閱讀5頁,還剩99頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第5章繼承、接口與泛型本章導讀1、子類與父類2、子類的繼承性3、子類對象的構造過程4、成員變量隱藏和方法的重寫5、super關鍵字6、final類與final方法7、對象的上轉型對象本章導讀8、繼承與多態(tài)9、使用abstract類10、面向抽象11、接口12、接口回調13、內部類14、匿名類15、異常類5.1子類與父類繼承是一種由已有的類創(chuàng)建新類的機制。利用繼承,我們可以先創(chuàng)建一個共有屬性的一般類,根據該一般類再創(chuàng)建具有特殊屬性的新類,新類繼承一般類的狀態(tài)和行為,并根據需要增加它自己的新的狀態(tài)和行為。由繼承而得到的類稱為子類,被繼承的類稱為父類(超類)。父類可以是自己編寫的類也可以是java類庫中的類。利用繼承有利于實現(xiàn)代碼的重復使用,子類只需要添加新的功能代碼即可。Java不支持多重繼承,即子類只能有一個父類。使用關鍵字extends來聲明一個類是另外一個類的子類,格式如下:如果一個類的聲明中沒有使用extends,這個類被默認為是Object的子類;Object是包java.lang中的類class子類名extends父類名{ …..}classAextendsObject{ …..}classA{ …..}返回說明:java.lang

類Objectjava.lang.Object

publicclassObject類Object是類層次結構的根類。每個類都使用Object作為超類。所有對象(包括數組)都實現(xiàn)這個類的方法。5.2子類的繼承性1.繼承的定義所謂類繼承就是子類繼承父類的成員變量和方法作為自己的成員變量和方法,就好象它們是在子類中直接聲明一樣。類A類Bpublicintf();privateintg;publiccharh();2.子類和父類在同一包中的繼承性子類能夠繼承父類共有的、受保護的和友好的成員,繼承成員的訪問權限不變子類不能繼承父類私有的成員例5-1,Son是Father的子類,而GrandSon是Son的子類,注意類的繼承3.類和父類不在同一包中的繼承性子類只能繼承父類共有的和受保護的成員,繼承成員的訪問權限不變子類不能繼承父類友好的和私有的成員classFather{privateintmoneyDollar=300;intmoneyHK=200;intadd(intx,inty){returnx+y;}}classSonextendsFather{intmoneyRMB=800;publicvoidchangMoneyHK(intx){moneyHK=x;}publicvoidchangMoneyRMB(intx){moneyRMB=x;}

例5-1intsubs(intx,inty){returnx-y;}}classGrandSonextendsSon{intmulti(intx,inty){returnx*y;}}publicclassExample5_1{publicstaticvoidmain(Stringargs[]){inta=5,b=3;Sonson=newSon();GrandSonsunzi=newGrandSon();son.changMoneyHK(666);son.changMoneyRMB(5000);

System.out.println("兒子的港幣是繼承的屬性,當前的值是:"+son.moneyHK);System.out.println("兒子的人民幣是新增的屬性,當前的值是:"+son.moneyRMB);System.out.printf("減法是兒子新增的功能,%d-%d等于%d\n",a,b,son.subs(a,b));System.out.printf("加法是兒子繼承的功能,%d+%d等于%d\n",a,b,son.add(a,b));System.out.println("孫子的港幣和人民幣都是繼承的屬性,當前的值是:");System.out.println("港幣:"+sunzi.moneyHK+"人民幣:"+sunzi.moneyRMB);System.out.printf("乘法是孫子新增的功能,%d*%d等于%d\n",a,b,sunzi.multi(a,b));

System.out.printf("加法是孫子繼承的功能,%d+%d等于%d\n",a,b,sunzi.add(a,b));System.out.printf("減法是孫子繼承的功能,%d-%d等于%d\n",a,b,sunzi.subs(a,b));}}運行結果:兒子的港幣是繼承的屬性,當前的值是:666兒子的人民幣是新增的屬性,當前的值是:5000減法是兒子新增的功能,5-3等于2加法是兒子繼承的功能,5+3等于8孫子的港幣和人民幣都是繼承的屬性,當前的值是:港幣:200人民幣:800乘法是孫子新增的功能,5*3等于15加法是孫子繼承的功能,5+3等于8減法是孫子繼承的功能,5-3等于2表5.1各種成員的繼承性子類與父類的相對位置public成員protected成員private成員友好成員在同一個包中允許允許不允許允許不在同一個包中允許允許不允許不允許返回5.3子類對象的構造過程步驟(2步):1、子類的構造方法總是先調用父類的某個構造方法(如果子類的構造方法沒有指明使用父類的哪個構造方法,將調用父類的不帶參數的構造方法)父類的成員變量都分配了內存空間,但只將其中一部分(允許繼承的那部分)做為子類對象的成員變量2、為子類中聲明的成員變量分配空間,執(zhí)行子類構造方法中的語句子類對象內存示意圖例5-2,子類調用繼承的方法操作未被子類繼承的父類成員變量子類未繼承的成員×子類對象子類未繼承的成員×子類繼承的成員√子類聲明的成員●子類聲明的成員●子類聲明的成員●子類繼承的成員√返回classA{privateintx=10;protectedinty=20;voidf(){y=y+x;System.out.printf("x=%d,y=%d\n",x,y);}}classBextendsA{voidg(){y=y+1;System.out.printf("y=%d\n",y);}}例5-2classExample5_2{publicstaticvoidmain(Stringargs[]){Bb=newB();b.g();//調用子類自己聲明的方法

b.f();//調用從父類繼承的方法

b.g();//調用子類自己聲明的方法

}}運行結果:y=21x=10,y=31y=325.4成員變量的隱藏和方法的重寫成員變量的隱藏當在子類中定義的成員變量和父類中的成員變量同名時,這個子類中定義的成員變量就隱藏(屏蔽)了從父類中繼承的同名成員變量。如果子類想使用被隱藏的成員變量,必須在成員變量名前加關鍵字super。例5-3,子類隱藏了從父類繼承的double型變量。classA{publicdoubley=11.456789;publicvoidf(){y=y+1;System.out.printf("y是double型的變量,y=%f\n",y);}}classBextendsA{inty=0;publicvoidg(){y=y+100;System.out.printf("y是int型的變量,y=%d\n",y);}}例5-3注:上面程序中B類中inty=0;語句的int不能省略,即不能寫為:y=0;因為(1)對成員變量的操作只能放在方法中,方法可以對成員變量進行操作形成算法。(2)類的成員類型中可以有數據和方法(即數據的定義和方法的定義)但不能有語句,語句必須放在方法中。classExample5_3{publicstaticvoidmain(Stringargs[]){Bb=newB();b.y=200;b.g();//調用子類新增的方法

b.f();//調用子類繼承的方法

}}y是int型的變量,y=300y是double型的變量,y=12.456789運行結果:方法重寫定義:子類中定義一個方法,并且這個方法的名字、返回類型、參數的個數和類型與從父類繼承的方法完全相同。作用:子類通過方法的重寫可以把父類的狀態(tài)和行為改變?yōu)樽陨淼臓顟B(tài)和行為。通過方法重寫,子類可以隱藏繼承的方法。如果子類想使用被隱藏的方法,必須使用關鍵字super。例5-4可以幫助我們更好的理解方法的重寫classA{protecteddoublex=8.0,y=0.888888;publicvoidspeak(){System.out.println("我喜歡NBA");}publicvoidcry(){y=x+y;System.out.printf("y=%f\n",y);}}classBextendsA{inty=100,z;publicvoidspeak(){z=2*y;System.out.println("IloveThisGame");System.out.printf("y=%d,z=%d",y,z);}}例5-4classExample5_4{publicstaticvoidmain(Stringargs[]){Bb=newB();b.cry();b.speak();}}y=8.888888IloveThisGamey=100,z=200運行結果:注意的問題:方法重寫時一定要保證方法的名字、類型、參數個數和類型同父類的某個方法完全相同,只有這樣,子類繼承的這個方法才被隱藏。如果子類在準備隱藏繼承的方法時,參數個數或參數類型與父類的方法不盡相同,那實際上也沒有隱藏繼承的方法,這時子類就出現(xiàn)兩個方法具有相同的名字。例5-5,子類沒有隱藏父類的方法。重寫父類方法時,不可降低父類方法的訪問權限。classA{publicintf(intx,inty){returnx+y;}}classBextendsA{publicintf(bytex,inty){returnx*y;}}例5-5publicclassExample5_5{publicstaticvoidmain(Stringargs[]){intz=0;Bb=newB();z=b.f(10,10);//z的值是20System.out.println(z);z=b.f((byte)10,10);//z的值是100System.out.println(z);}}20100運行結果:對protected的進一步說明問題:類C間接繼承了類A,用類C定義一個對象c,討論對象c什么時候具有訪問由繼承而來的受保護的成員的權限(h和f())。情況1:若對象c是在類C中創(chuàng)建的,則對象c具有訪問h和f()的權限。情況2:若對象c是在類Other中用類C創(chuàng)建的,且類Other與類C的祖先類A在同一個包內,則對象c具有訪問h和f()的權限。情況3:若對象c是在類Other中用類C創(chuàng)建的,且類Other與類C的祖先類A不在同一個包內,則對象c不具有訪問h和f()的權限。類A類Bprotectedintf();類Cprotectedinth;返回5.5super關鍵字1.使用super調用父類的構造方法子類不繼承父類的構造方法子類如果想使用父類的構造方法,必須在子類的構造方法中使用關鍵字super來調用父類的構造方法super必須是子類構造方法中的第一條語句(子類在創(chuàng)建對象時,總是先調用父類的構造方法)例5-6,子類的構造方法中使用super調用父類的構造方法返回classA{intx,y;A(){x=100;y=200;}A(intx,inty){this.x=x;this.y=y;}}classBextendsA{intz;B(intx,inty){

super(x,y);z=300;}

例5-6B(){

super();//可以省略

z=800;}publicvoidf(){System.out.printf("x=%d,y=%d,z=%d\n",x,y,z);}}publicclassExample5_6{publicstaticvoidmain(Stringargs[]){Bb1=newB(10,20);b1.f();Bb2=newB();b2.f();}}x=10,y=20,z=300x=100,y=200,z=800運行結果:5.5super關鍵字2.使用super操作被隱藏的成員變量和方法例5-7classA{intm=0,n=0;longf(){returnm+n;}}classBextendsA{intm=1,n=1;longf(){longresult=0;

super.m=10;super.n=20;result=super.f()+(m+n);returnresult;}

例5-7longg(){longresult=0;

result=super.f();returnresult/2;}}publicclassExample5_7{publicstaticvoidmain(Stringargs[]){Bb=newB();b.m=3;b.n=7;longresultOne=b.g();longresultTwo=b.f();longresultThree=b.g();System.out.println("resultOne="+resultOne);System.out.println("resultTwo="+resultTwo);System.out.println("resultThree="+resultThree);}}resultOne=0resultTwo=40resultThree=15運行結果:5.6final類和final方法final類在定義一個類時,如果用關鍵字final修飾該類,則該類就是final類,如:finalclassA{…}final類不能被繼承,即不能有子類將一個類聲明為final類一般是由于安全性考慮,例如Java提供的String類final方法如果一個方法被修飾為final方法,則這個方法不能被重寫,即不允許子類通過重寫來隱藏繼承的final方法返回5.7對象的上轉型對象對象a是子類對象b的上轉型對象;對象的上轉型實際上就是利用超類的引用操作子類的對象上轉型對象會失去原對象的一些屬性和功能(上轉型對象不能操作子類新聲明定義的成員變量(失掉了這部分屬性),不能使用子類新聲明定義的方法(失掉了一些功能))類A類BAa;Bb=newB();a=b;繼承或隱藏的成員變量繼承或重寫的成員方法新增的成員變量新增的成員方法對象上轉型對象

上轉型對象可以操作子類繼承的成員變量和隱藏的成員變量,也可以使用子類繼承的或重寫的方法(如果子類重寫了父類的某個方法后,對象的上轉型對象調用這個方法時,一定是調用了這個重寫的方法)。當把對象的上轉型對象再強制轉換到一個子類對象后,該子類對象又具備了子類所有屬性和功能。例5-8,使用了上轉型對象不可以將父類創(chuàng)建對象的引用賦值給子類聲明的對象返回classA{doublen;intm;voidf(){System.out.printf("子類繼承方法f(),n=%f,m=%d\n",n,m);}voidg(){System.out.printf("你好,n=%f,m=%d\n",n,m);}}classBextendsA{intn=12;voidg(){System.out.printf("子類重寫方法g(),n=%d,m=%d\n",n,m);}

例5-8voidcry(){System.out.printf("子類新增的方法,n=%d,m=%d\n",n,m);}}publicclassExample5_8{publicstaticvoidmain(Stringargs[]){Aa;a=newB();//a是子類對象的上轉型對象

a.n=0.618;//操作子類隱藏的double類型成員na.m=200;//操作子類繼承的成員m,等價于b.m=200;a.f(); //調用子類繼承的方法,等價于b.f();a.g();//調用子類重寫的方法,等價于b.g();

Bb=(B)a; //上轉型對象強制轉換成子類對象

b.n=555; //操作子類新增的int類型成員nb.cry(); //a.cry();是非法的

}}子類繼承方法f(),n=0.618000,m=200子類重寫方法g(),n=12,m=200子類新增的方法,n=555,m=200Example5_8.java運行結果:5.8繼承與多態(tài)

與繼承有關的多態(tài)性是指父類的某個實例方法被其子類重寫時,可以各自產生自己的功能行為,即同一個操作被不同類型對象調用時可能產生不同的行為。5.8繼承與多態(tài)AnimalAnimala;a=newDog();a.move();a=newFish();a.move();a=newBird();a.move();move(){move;}Dogmove(){run;}Fishmove(){swim;}Birdmove(){fly;}run;

swim;

fly;

當一個類有很多子類時,并且這些子類都重寫了父類中的某個方法。當我們把子類創(chuàng)建的對象的引用放到一個父類的對象中時,就得到了該對象的一個上轉型對象,那么這個上轉型對象在調用這個方法時就可能具有多種形態(tài)。和繼承有關的多態(tài)性是指父類的某個方法被其子類重寫時,可以產生自己的功能行為,即同一個操作被不同類型對象調用時可能產生不同的行為。因為不同的子類在重寫父類的方法時可能產生不同的行為;也就是說,不同對象的上轉型對象調用同一方法可能產生不同的行為。例5-9返回classAnimal{voidcry(){}}classDogextendsAnimal{voidcry(){System.out.println("Wang!Wang!......");}}classCatextendsAnimal{voidcry(){System.out.println("miao~~miao~~...");}}例5-9publicclassExample5_9{publicstaticvoidmain(Stringargs[]){Animalanimal;animal=newDog();//animal是Dog對象的上轉型對象

animal.cry();animal=newCat();//animal是Cat對象的上轉型對象

animal.cry();}}Wang!Wang!......miao~~miao~~...Example5_9.java的運行結果:5.9使用abstract類abstract方法:只允許聲明,而不允許實現(xiàn)(將功能的聲明和功能的實現(xiàn)分離開來)abstractvoidmove();如果一個類中含有abstract方法,那么這個類必須用abstract來修飾。用關鍵字abstract修飾類稱為abstract類(抽象類)。abstractclassA{ ……}5.9使用abstract類抽象類的特點:(1)abstract類可以有abstract方法,也可以有非abstract方法。抽象方法只允許聲明,不允許實現(xiàn),不允許final和abstract同時修飾一個方法。抽象類的特點:

下面類中的min()就是abstract方法。abstractclassA{abstractintmin(intx,inty);intmax(intx,inty){returnx>y?x:y;}}抽象類的特點:

(2)抽象類不能用new運算符創(chuàng)建對象

abstract類不能用new運算符創(chuàng)建對象,必須產生其子類,子類必須實現(xiàn)abstract方法,即重寫父類的abstract方法,再由子類創(chuàng)建對象。一個abstract類只關心子類是否具有某種功能,不關心功能的具體實現(xiàn),具體實現(xiàn)由子類負責。如果一個非抽象類是某個抽象類的子類,那么它必須重寫父類的抽象方法,給出方法體,即在子類中將abstract方法重新聲明,但必須去掉abstract修飾,同時要保證聲明的方法名字、返回類型、參數個數和類型與父類的abstract方法完全相同。抽象類的特點:(3)做上轉型對象抽象類不能創(chuàng)建對象,但它的非抽象類子類需重寫它的全部abstract方法,這樣就可以讓該抽象類聲明的對象成為其子類對象的上轉型對象,并調用其子類重寫的方法。

abstract類可以沒有abstract方法(此時是強調不能用該類構建對象)。如果一個抽象類是另一個抽象類的子類,它可以重寫其父類的abstract方法,也可以繼承這個abstract方法。

5.10面向抽象軟件設計好之后,都希望更加容易維護,當增加或修改某部分時,不必修改其他部分;要想使得軟件容易維護,軟件的設計就顯得非常重要。開-閉原則:就是一個程序應當對擴展開放,對修改關閉。面向抽象的核心思想如下:抽象細節(jié):面向抽象的第一步就是將經常需要變化的部分分割出來,將其作為abstract類中的abstract方法,不讓設計者去關心實現(xiàn)的細節(jié),避免所設計的類依賴于這些細節(jié)。面向抽象設計類:面向抽象編程的第二步就是面向抽象類來設計一個新類。例5-10例5-10//Geometry.javapublicabstractclassGeometry{publicabstractdoublegetArea();}將Geometry.java、Pillar.java、Lader.java、Circle.java保存在D:\java中編譯通過,編寫一個應用程序,計算具有Circle底和Lader底的柱體的體積。(注:可把下面所有的文件放在D:\java中,直接編譯Example5_10.java和執(zhí)行Example5_10。//Pillar.javapublicclassPillar{Geometrybottom;//將Geometry對象作為成員

doubleheight;Pillar(Geometrybottom,doubleheight){this.bottom=bottom;this.height=height;}voidchangeBottom(Geometrybottom){this.bottom=bottom;}publicdoublegetVolume(){returnbottom.getArea()*height;//bottom可以調用子類重寫的getArea方法

}}例5-10//Lader.javapublicclassLaderextendsGeometry{doublea,b,h;Lader(doublea,doubleb,doubleh){this.a=a;this.b=b;this.h=h;}publicdoublegetArea(){return((1/2.0)*(a+b)*h);}}例5-10//Circle.javapublicclassCircleextendsGeometry{doubler;Circle(doubler){this.r=r;}publicdoublegetArea(){return(3.14*r*r);}}例5-10//Example5_10.javapublicclassExample5_10{publicstaticvoidmain(Stringargs[]){Pillarpillar;Geometrytuxing;tuxing=newLader(12,22,100);System.out.println("梯形的面積"+tuxing.getArea());pillar=newPillar(tuxing,58);System.out.println("梯形底的柱體的體積"+pillar.getVolume());tuxing=newCircle(10);System.out.println("半徑是10的圓的面積"+tuxing.getArea());pillar.changeBottom(tuxing);System.out.println("圓形底的柱體的體積"+pillar.getVolume());}}例5-10D:\java>javacExample5_10.javaD:\java>javaExample5_10梯形的面積1700.0梯形底的柱體的體積98600.0半徑是10的圓的面積314.0圓形底的柱體的體積18212.05.11接口Java不支持多繼承性,即一個類只能有一個父類;為了克服單繼承的缺點,Java使用了接口,一個類可以實現(xiàn)多個接口。使用關鍵字interface來定義一個接口。關鍵字interface是將abstract的概念做了更進一步的發(fā)揮,可以想像它是“純粹”的abstractclass。1、接口的聲明與使用2、Java的繼承體系5.11.1接口的聲明與使用接口通過使用關鍵字interface來聲明,其格式如下:interface接口名{接口體}interfacePrintable{finalintMax=100;floatsum(floatx,floaty);}接口體中包含常量定義和方法定義兩部分接口體中可以含數據成員,但這些數據成員自然而然成為static和final。接口體中只進行方法的聲明,不許提供方法的實現(xiàn),所以,方法的定義沒有方法體,且用分號“;”結尾。一個類通過使用關鍵字implements聲明自己實現(xiàn)一個或多個接口;如果實現(xiàn)多個接口,用逗號隔開接口名classAimplementsPrintable{…}//類B實現(xiàn)接口Printable和接口AddableclassBimplementsPrintable,Addable{…}//從類Animal繼承的類Dog實現(xiàn)接口EatableclassDogextendsAnimalimplementsEatable{…}注意的問題:如果一個類實現(xiàn)某個接口,那么這個類必須實現(xiàn)該接口的所有方法,即為這些方法提供方法體。接口中的方法被默認是public和abstract的,接口在聲明方法時可以省略方法前面的public和abstract關鍵字;但是,類在實現(xiàn)接口方法時,一定要用public來修飾。類實現(xiàn)的接口方法以及接口中的常量可以被類的對象調用。Java提供的接口都在相應的包中,通過引入包可以使用Java提供的接口,也可以自己定義接口。一個Java源程序就是由類和接口組成的。interface前面加public,public接口可被任意類使用,如果前面不加public修飾,稱為友好接口,可以被同一包中的類使用。如果父類實現(xiàn)了某個接口,則其子類也就自然實現(xiàn)這個接口,子類不必用implements聲明自己實現(xiàn)這個接口。接口也可以被繼承,即可以通過關鍵字extends聲明一個接口是另一個接口的子接口。interfaceComputable{finalintMAX=100;intf(intx);

publicabstractintg(intx,inty);}classAimplementsComputable{

publicintf(intx){returnx*x;}

publicintg(intx,inty){returnx+y;}}例5-11例5-11,類實現(xiàn)接口classBimplementsComputable{

publicintf(intx){returnx*x*x;}

publicintg(intx,inty){returnx*y;}}publicclassExample5_11{publicstaticvoidmain(Stringargs[]){Aa=newA();Bb=newB();System.out.println(a.MAX);System.out.println(""+a.f(10)+""+a.g(12,6));System.out.println(b.MAX);System.out.println(""+b.f(10)+""+b.g(29,2));}}D:\java>javacExample5_11.javaD:\java>javaExample5_1110010018100100058Java支持繼承,但不支持多繼承性,即一個類只能有一個父類單繼承使得Java簡單,程序更加容易維護和健壯多繼承使得編程更加靈活,Java使用接口來獲得類似于多繼承的靈活性返回接口的思想在于它可以增加很多類都需要實現(xiàn)的功能,使用相同的接口類不一定有繼承關系,同一個類也可以實現(xiàn)多個接口

baseclass1interface1interface2class25.11.2Java的繼承體系5.12接口的回調interfaceAnimalAnimala;a=newDog();a.move();a=newFish();a.move();a=newBird();a.move();move();Dogmove(){run;}Fishmove(){swim;}Birdmove(){fly;}run;

swim;

fly;

1.接口回調把實現(xiàn)某一接口的類創(chuàng)建的對象的引用賦給該接口聲明的接口變量中,該接口變量就可以調用被類實現(xiàn)的接口中的方法;當接口變量調用被類實現(xiàn)的接口中的方法時,就是通知相應的對象調用接口的方法,這一過程稱作對象功能的接口回調接口回調是多態(tài)的另一種體現(xiàn)例5-12使用了接口的回調技術返回interfaceShowMessage{voidshowTradeMark();}classTVimplementsShowMessage{

publicvoidshowTradeMark(){System.out.println("我是電視機");}}classPCimplementsShowMessage{

publicvoidshowTradeMark(){System.out.println("我是電腦");}}例5-12publicclassExample5_12{publicstaticvoidmain(Stringargs[]){ShowMessagesm;//聲明接口變量smsm=newTV();//接口變量sm中存放對象的引用

sm.showTradeMark();//接口sm回調showTradeMark()方法

sm=newPC();//接口變量sm中存放對象的引用

sm.showTradeMark();//接口回調

}}D:\java>javacExample5_12.javaD:\java>javaExample5_12我是電視機我是電腦5.12接口的回調2.接口作為參數當一個方法的參數是一個接口類型時,如果一個類實現(xiàn)了該接口,那么就可以把該類的實例的引用傳值給該參數,參數可以回調類實現(xiàn)的接口方法。例5-13使用接口作為參數interfaceShow{voidshow();}classAimplementsShow{publicvoidshow(){System.out.println("IloveThisGame");}}classBimplementsShow{publicvoidshow(){System.out.println("我喜歡看NBA");}}例5-13classC{publicvoidf(Shows){//接口作為參數

s.show();//參數s回調類實現(xiàn)的接口方法

}}publicclassExample5_13{publicstaticvoidmain(Stringargs[]){Cc=newC();c.f(newA());c.f(newB());}}D:\java>javacExample5_13.javaD:\java>javaExample5_13IloveThisGame我喜歡看NBA5.13面向接口面向接口也可以體現(xiàn)程序設計的“開-閉”原理(Open-ClosedPrinciple),即對擴展開放,對修改關閉將自己經常需要變化的細節(jié)分割出來,作為接口中的abstract方法然后面向接口來設計類。例5-14Pillar類將自己經常需要變化的細節(jié)分離出來,作為接口Geometry中的抽象方法,然后面向接口Geometry來設計Pillar類,即Pillar類把Geometry定義的接口變量作為其中的成員,當程序再增加一個實現(xiàn)接口Geometry的D類時,接口變量所在的Pillar類不需要做任何修改,接口變量就可以回調D類實現(xiàn)的接口方法。返回//Example5_14.javapublicclassExample5_14{publicstaticvoidmain(Stringargs[]){Pillarpillar;Geometrytuxing;//接口變量

tuxing=newLader(12,22,100);System.out.println("梯形的面積"+tuxing.getArea());pillar=newPillar(tuxing,58);System.out.println("梯形底的柱體的體積"+pillar.getVolume());tuxing=newCircle(10);System.out.println("半徑是10的圓的面積"+tuxing.getArea());

pillar.changeBottom(tuxing);System.out.println("圓形底的柱體的體積"+pillar.getVolume());}}//Geometry.javapublicinterfaceGeometry{publicabstractdoublegetArea();}//Pillar.javapublicclassPillar{

Geometrybottom;//將bottom接口變量作為成員

doubleheight;Pillar(Geometrybottom,doubleheight){this.bottom=bottom;this.height=height;}voidchangeBottom(Geometrybottom){this.bottom=bottom;}publicdoublegetVolume(){returnbottom.getArea()*height;//bottom可以回調類//實現(xiàn)的接口方法getArea()}}//Lader.javapublicclassLaderimplementsGeometry{doublea,b,h;Lader(doublea,doubleb,doubleh){this.a=a;this.b=b;this.h=h;}publicdoublegetArea(){return((1/2.0)*(a+b)*h);}}//Circle.javapublicclassCircleimplementsGeometry{doubler;Circle(doubler){this.r=r;}publicdoublegetArea(){return(3.14*r*r);}}D:\java>javacExample5_14.javaD:\java>javaExample5_14梯形的面積1700.0梯形底的柱體的體積98600.0半徑是10的圓的面積314.0圓形底的柱體的體積18212.05.14抽象類與接口的比較abstract類和接口都可以有abstract方法。接口中只可以有常量,不能有變量;而abstract類中即可以有常量也可以有變量。abstract類中也可以有非abstract方法,接口不可以。在設計程序中對抽象類和接口的選擇:(1)某個問題需要使用繼承,如除了需要實現(xiàn)父類的抽象方法,還需要從父類繼承一些變量或繼承一些重要的非抽象方法,需要考慮用抽象類。(2)某個問題不需要繼承,只需要若干個類給出某些重要的抽象方法的實現(xiàn)細節(jié),可以考慮用接口。返回5.15內部類類可以有兩種重要的成員:成員變量和方法;類還可以有一種成員:內部類。Java支持在一個類中聲明另一個類,這樣的類稱作內部類,而包含內部類的類成為內部類的外嵌類。內部類同類中聲明的方法或成員變量一樣,一個類把內部類看作是自己的成員。外嵌類的成員變量在內部類中仍然有效,內部類中的方法也可以調用外嵌類中的方法。內部類的類體中不可以聲明類變量和類方法。外嵌類可以用內部類聲明對象,作為外嵌類的成員。例5-15給出了內部類的用法返回classNorthEast{Stringland="黑土地";}classChina{intx=10,y=10;LiaoNingdalian;//內部類聲明的對象作為外嵌類的成員

China(){dalian=newLiaoNing();}voidf(){System.out.println("我是中國");dalian.speak();}

例5-15classLiaoNingextendsNorthEast{//內部類的聲明

intz;voidspeak(){System.out.println("我是大連,z="+z+":"+land);}voidg(){z=x+y;//使用外嵌類中的x,yf();//調用外嵌類中的方法f()}

}//內部類結束}publicclassExample5_15{publicstaticvoidmain(Stringargs[]){Chinachina=newChina();china.f();china.dalian.g();}}我是中國我是大連,z=0:黑土地我是中國我是大連,z=20:黑土地運行結果:5.16匿名類就是沒有名字的類。1、與類有關的匿名類2、與接口有關的匿名類當使用類創(chuàng)建對象時,程序允許我們把類體與對象的創(chuàng)建組合在一起,也就是說,類創(chuàng)建對象時,除了構造方法還有類體,此類體被認為是該類的一個子類去掉類聲明后的類體,稱作匿名類。匿名類就是一個子類,由于無名可用,所以不可能用匿名類聲明對象,但卻可以直接用匿名類創(chuàng)建一個對象。假設Hello是類,那么下列代碼就是用Hello的一個子類(匿名類)創(chuàng)建對象。newHello(){

匿名類的類體};5.16.1與類有關的匿名類匿名類可以繼承類的方法也可以重寫類的方法。使用匿名類時,必然是在某個類中直接用匿名類創(chuàng)建對象,因此匿名類一定是內部類,匿名類可以訪問外嵌類中的成員變量和方法。匿名類不可以聲明static成員變量和static方法。匿名類的主要用途就是向方法的參數傳值。說明:

匿名類的特點:(1)匿名類不取名字,而直接用其父類的名字或者它所實現(xiàn)的接口的名字。(2)類的定義與創(chuàng)建該類的一個實例同時進行,即類的定義前面有一個new。不使用關鍵詞class,同時帶上()表示創(chuàng)建對象。也就是說,匿名類的定義方法是:

new類名或接口名(){……}(3)類名前面不能有修飾符。(4)類中不能定義構造方法,因為它沒有名字。也正是這個原因,在構造對象時,也不能帶參數,因為默認構造方法不能帶參數。abstractclassStudent{abstractvoidspeak();}classTeacher{voidlook(Studentstu){stu.speak();//執(zhí)行匿名類體中重寫的speak()方法

}}publicclassExample5_16{publicstaticvoidmain(Stringargs[]){

Teacherzhang=newTeacher();zhang.look(newStudent(){//匿名類的類體,即//Student的子類的類體

例5-16展示了匿名類的用法voidspeak(){System.out.println("這是匿名類中的方法");}}//匿名類類體結束

);}}這是匿名類中的方法運行結果:假設Animal是一個接口,Java允許直接用接口名和一個類體創(chuàng)建一個匿名對象,此類體被認為是實現(xiàn)了Animal接口的類去掉類聲明后的類體,稱作匿名類。假設Hello是接口,那么下列代碼就是用Hello的一個子類(匿名類)創(chuàng)建對象newHello(){

實現(xiàn)接口的匿名類的類體};例5-17展示了和接口有關的匿名類的用法返回5.16.2與接口有關的匿名類interfaceShow{

publicvoidshow();}classA{voidf(Shows){s.show();//s調用匿名類體中實現(xiàn)的接口方法(接口回調)

}}publicclassExample5_17{publicstaticvoidmain(Stringargs[]){Aa=newA();a.f(newShow(){publicvoidsh

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論