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

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

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

類Objectjava.lang.Object

publicclassObject類Object是類層次結(jié)構(gòu)的根類。每個(gè)類都使用Object作為超類。所有對(duì)象(包括數(shù)組)都實(shí)現(xiàn)這個(gè)類的方法。5.2子類的繼承性1.繼承的定義所謂類繼承就是子類繼承父類的成員變量和方法作為自己的成員變量和方法,就好象它們是在子類中直接聲明一樣。類A類Bpublicintf();privateintg;publiccharh();2.子類和父類在同一包中的繼承性子類能夠繼承父類共有的、受保護(hù)的和友好的成員,繼承成員的訪問權(quán)限不變子類不能繼承父類私有的成員例5-1,Son是Father的子類,而GrandSon是Son的子類,注意類的繼承3.類和父類不在同一包中的繼承性子類只能繼承父類共有的和受保護(hù)的成員,繼承成員的訪問權(quán)限不變子類不能繼承父類友好的和私有的成員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("兒子的港幣是繼承的屬性,當(dāng)前的值是:"+son.moneyHK);System.out.println("兒子的人民幣是新增的屬性,當(dāng)前的值是:"+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("孫子的港幣和人民幣都是繼承的屬性,當(dāng)前的值是:");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));}}運(yùn)行結(jié)果:兒子的港幣是繼承的屬性,當(dāng)前的值是:666兒子的人民幣是新增的屬性,當(dāng)前的值是:5000減法是兒子新增的功能,5-3等于2加法是兒子繼承的功能,5+3等于8孫子的港幣和人民幣都是繼承的屬性,當(dāng)前的值是:港幣:200人民幣:800乘法是孫子新增的功能,5*3等于15加法是孫子繼承的功能,5+3等于8減法是孫子繼承的功能,5-3等于2表5.1各種成員的繼承性子類與父類的相對(duì)位置public成員protected成員private成員友好成員在同一個(gè)包中允許允許不允許允許不在同一個(gè)包中允許允許不允許不允許返回5.3子類對(duì)象的構(gòu)造過程步驟(2步):1、子類的構(gòu)造方法總是先調(diào)用父類的某個(gè)構(gòu)造方法(如果子類的構(gòu)造方法沒有指明使用父類的哪個(gè)構(gòu)造方法,將調(diào)用父類的不帶參數(shù)的構(gòu)造方法)父類的成員變量都分配了內(nèi)存空間,但只將其中一部分(允許繼承的那部分)做為子類對(duì)象的成員變量2、為子類中聲明的成員變量分配空間,執(zhí)行子類構(gòu)造方法中的語句子類對(duì)象內(nèi)存示意圖例5-2,子類調(diào)用繼承的方法操作未被子類繼承的父類成員變量子類未繼承的成員×子類對(duì)象子類未繼承的成員×子類繼承的成員√子類聲明的成員●子類聲明的成員●子類聲明的成員●子類繼承的成員√返回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();//調(diào)用子類自己聲明的方法

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

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

}}運(yùn)行結(jié)果:y=21x=10,y=31y=325.4成員變量的隱藏和方法的重寫成員變量的隱藏當(dāng)在子類中定義的成員變量和父類中的成員變量同名時(shí),這個(gè)子類中定義的成員變量就隱藏(屏蔽)了從父類中繼承的同名成員變量。如果子類想使用被隱藏的成員變量,必須在成員變量名前加關(guān)鍵字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;因?yàn)椋?)對(duì)成員變量的操作只能放在方法中,方法可以對(duì)成員變量進(jìn)行操作形成算法。(2)類的成員類型中可以有數(shù)據(jù)和方法(即數(shù)據(jù)的定義和方法的定義)但不能有語句,語句必須放在方法中。classExample5_3{publicstaticvoidmain(Stringargs[]){Bb=newB();b.y=200;b.g();//調(diào)用子類新增的方法

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

}}y是int型的變量,y=300y是double型的變量,y=12.456789運(yùn)行結(jié)果:方法重寫定義:子類中定義一個(gè)方法,并且這個(gè)方法的名字、返回類型、參數(shù)的個(gè)數(shù)和類型與從父類繼承的方法完全相同。作用:子類通過方法的重寫可以把父類的狀態(tài)和行為改變?yōu)樽陨淼臓顟B(tài)和行為。通過方法重寫,子類可以隱藏繼承的方法。如果子類想使用被隱藏的方法,必須使用關(guān)鍵字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運(yùn)行結(jié)果:注意的問題:方法重寫時(shí)一定要保證方法的名字、類型、參數(shù)個(gè)數(shù)和類型同父類的某個(gè)方法完全相同,只有這樣,子類繼承的這個(gè)方法才被隱藏。如果子類在準(zhǔn)備隱藏繼承的方法時(shí),參數(shù)個(gè)數(shù)或參數(shù)類型與父類的方法不盡相同,那實(shí)際上也沒有隱藏繼承的方法,這時(shí)子類就出現(xiàn)兩個(gè)方法具有相同的名字。例5-5,子類沒有隱藏父類的方法。重寫父類方法時(shí),不可降低父類方法的訪問權(quán)限。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運(yùn)行結(jié)果:對(duì)protected的進(jìn)一步說明問題:類C間接繼承了類A,用類C定義一個(gè)對(duì)象c,討論對(duì)象c什么時(shí)候具有訪問由繼承而來的受保護(hù)的成員的權(quán)限(h和f())。情況1:若對(duì)象c是在類C中創(chuàng)建的,則對(duì)象c具有訪問h和f()的權(quán)限。情況2:若對(duì)象c是在類Other中用類C創(chuàng)建的,且類Other與類C的祖先類A在同一個(gè)包內(nèi),則對(duì)象c具有訪問h和f()的權(quán)限。情況3:若對(duì)象c是在類Other中用類C創(chuàng)建的,且類Other與類C的祖先類A不在同一個(gè)包內(nèi),則對(duì)象c不具有訪問h和f()的權(quán)限。類A類Bprotectedintf();類Cprotectedinth;返回5.5super關(guān)鍵字1.使用super調(diào)用父類的構(gòu)造方法子類不繼承父類的構(gòu)造方法子類如果想使用父類的構(gòu)造方法,必須在子類的構(gòu)造方法中使用關(guān)鍵字super來調(diào)用父類的構(gòu)造方法super必須是子類構(gòu)造方法中的第一條語句(子類在創(chuàng)建對(duì)象時(shí),總是先調(diào)用父類的構(gòu)造方法)例5-6,子類的構(gòu)造方法中使用super調(diào)用父類的構(gòu)造方法返回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運(yùn)行結(jié)果:5.5super關(guān)鍵字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運(yùn)行結(jié)果:5.6final類和final方法final類在定義一個(gè)類時(shí),如果用關(guān)鍵字final修飾該類,則該類就是final類,如:finalclassA{…}final類不能被繼承,即不能有子類將一個(gè)類聲明為final類一般是由于安全性考慮,例如Java提供的String類final方法如果一個(gè)方法被修飾為final方法,則這個(gè)方法不能被重寫,即不允許子類通過重寫來隱藏繼承的final方法返回5.7對(duì)象的上轉(zhuǎn)型對(duì)象對(duì)象a是子類對(duì)象b的上轉(zhuǎn)型對(duì)象;對(duì)象的上轉(zhuǎn)型實(shí)際上就是利用超類的引用操作子類的對(duì)象上轉(zhuǎn)型對(duì)象會(huì)失去原對(duì)象的一些屬性和功能(上轉(zhuǎn)型對(duì)象不能操作子類新聲明定義的成員變量(失掉了這部分屬性),不能使用子類新聲明定義的方法(失掉了一些功能))類A類BAa;Bb=newB();a=b;繼承或隱藏的成員變量繼承或重寫的成員方法新增的成員變量新增的成員方法對(duì)象上轉(zhuǎn)型對(duì)象

上轉(zhuǎn)型對(duì)象可以操作子類繼承的成員變量和隱藏的成員變量,也可以使用子類繼承的或重寫的方法(如果子類重寫了父類的某個(gè)方法后,對(duì)象的上轉(zhuǎn)型對(duì)象調(diào)用這個(gè)方法時(shí),一定是調(diào)用了這個(gè)重寫的方法)。當(dāng)把對(duì)象的上轉(zhuǎn)型對(duì)象再強(qiáng)制轉(zhuǎn)換到一個(gè)子類對(duì)象后,該子類對(duì)象又具備了子類所有屬性和功能。例5-8,使用了上轉(zhuǎn)型對(duì)象不可以將父類創(chuàng)建對(duì)象的引用賦值給子類聲明的對(duì)象返回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是子類對(duì)象的上轉(zhuǎn)型對(duì)象

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

Bb=(B)a; //上轉(zhuǎn)型對(duì)象強(qiáng)制轉(zhuǎn)換成子類對(duì)象

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運(yùn)行結(jié)果:5.8繼承與多態(tài)

與繼承有關(guān)的多態(tài)性是指父類的某個(gè)實(shí)例方法被其子類重寫時(shí),可以各自產(chǎn)生自己的功能行為,即同一個(gè)操作被不同類型對(duì)象調(diào)用時(shí)可能產(chǎn)生不同的行為。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;

當(dāng)一個(gè)類有很多子類時(shí),并且這些子類都重寫了父類中的某個(gè)方法。當(dāng)我們把子類創(chuàng)建的對(duì)象的引用放到一個(gè)父類的對(duì)象中時(shí),就得到了該對(duì)象的一個(gè)上轉(zhuǎn)型對(duì)象,那么這個(gè)上轉(zhuǎn)型對(duì)象在調(diào)用這個(gè)方法時(shí)就可能具有多種形態(tài)。和繼承有關(guān)的多態(tài)性是指父類的某個(gè)方法被其子類重寫時(shí),可以產(chǎn)生自己的功能行為,即同一個(gè)操作被不同類型對(duì)象調(diào)用時(shí)可能產(chǎn)生不同的行為。因?yàn)椴煌淖宇愒谥貙懜割惖姆椒〞r(shí)可能產(chǎn)生不同的行為;也就是說,不同對(duì)象的上轉(zhuǎn)型對(duì)象調(diào)用同一方法可能產(chǎn)生不同的行為。例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對(duì)象的上轉(zhuǎn)型對(duì)象

animal.cry();animal=newCat();//animal是Cat對(duì)象的上轉(zhuǎn)型對(duì)象

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

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

(2)抽象類不能用new運(yùn)算符創(chuàng)建對(duì)象

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

abstract類可以沒有abstract方法(此時(shí)是強(qiáng)調(diào)不能用該類構(gòu)建對(duì)象)。如果一個(gè)抽象類是另一個(gè)抽象類的子類,它可以重寫其父類的abstract方法,也可以繼承這個(gè)abstract方法。

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

doubleheight;Pillar(Geometrybottom,doubleheight){this.bottom=bottom;this.height=height;}voidchangeBottom(Geometrybottom){this.bottom=bottom;}publicdoublegetVolume(){returnbottom.getArea()*height;//bottom可以調(diào)用子類重寫的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不支持多繼承性,即一個(gè)類只能有一個(gè)父類;為了克服單繼承的缺點(diǎn),Java使用了接口,一個(gè)類可以實(shí)現(xiàn)多個(gè)接口。使用關(guān)鍵字interface來定義一個(gè)接口。關(guān)鍵字interface是將abstract的概念做了更進(jìn)一步的發(fā)揮,可以想像它是“純粹”的abstractclass。1、接口的聲明與使用2、Java的繼承體系5.11.1接口的聲明與使用接口通過使用關(guān)鍵字interface來聲明,其格式如下:interface接口名{接口體}interfacePrintable{finalintMax=100;floatsum(floatx,floaty);}接口體中包含常量定義和方法定義兩部分接口體中可以含數(shù)據(jù)成員,但這些數(shù)據(jù)成員自然而然成為static和final。接口體中只進(jìn)行方法的聲明,不許提供方法的實(shí)現(xiàn),所以,方法的定義沒有方法體,且用分號(hào)“;”結(jié)尾。一個(gè)類通過使用關(guān)鍵字implements聲明自己實(shí)現(xiàn)一個(gè)或多個(gè)接口;如果實(shí)現(xiàn)多個(gè)接口,用逗號(hào)隔開接口名classAimplementsPrintable{…}//類B實(shí)現(xiàn)接口Printable和接口AddableclassBimplementsPrintable,Addable{…}//從類Animal繼承的類Dog實(shí)現(xiàn)接口EatableclassDogextendsAnimalimplementsEatable{…}注意的問題:如果一個(gè)類實(shí)現(xiàn)某個(gè)接口,那么這個(gè)類必須實(shí)現(xiàn)該接口的所有方法,即為這些方法提供方法體。接口中的方法被默認(rèn)是public和abstract的,接口在聲明方法時(shí)可以省略方法前面的public和abstract關(guān)鍵字;但是,類在實(shí)現(xiàn)接口方法時(shí),一定要用public來修飾。類實(shí)現(xiàn)的接口方法以及接口中的常量可以被類的對(duì)象調(diào)用。Java提供的接口都在相應(yīng)的包中,通過引入包可以使用Java提供的接口,也可以自己定義接口。一個(gè)Java源程序就是由類和接口組成的。interface前面加public,public接口可被任意類使用,如果前面不加public修飾,稱為友好接口,可以被同一包中的類使用。如果父類實(shí)現(xiàn)了某個(gè)接口,則其子類也就自然實(shí)現(xiàn)這個(gè)接口,子類不必用implements聲明自己實(shí)現(xiàn)這個(gè)接口。接口也可以被繼承,即可以通過關(guān)鍵字extends聲明一個(gè)接口是另一個(gè)接口的子接口。interfaceComputable{finalintMAX=100;intf(intx);

publicabstractintg(intx,inty);}classAimplementsComputable{

publicintf(intx){returnx*x;}

publicintg(intx,inty){returnx+y;}}例5-11例5-11,類實(shí)現(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支持繼承,但不支持多繼承性,即一個(gè)類只能有一個(gè)父類單繼承使得Java簡單,程序更加容易維護(hù)和健壯多繼承使得編程更加靈活,Java使用接口來獲得類似于多繼承的靈活性返回接口的思想在于它可以增加很多類都需要實(shí)現(xiàn)的功能,使用相同的接口類不一定有繼承關(guān)系,同一個(gè)類也可以實(shí)現(xiàn)多個(gè)接口

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

swim;

fly;

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

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

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

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

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

sm.showTradeMark();//接口回調(diào)

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

s.show();//參數(shù)s回調(diào)類實(shí)現(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)程序設(shè)計(jì)的“開-閉”原理(Open-ClosedPrinciple),即對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉將自己經(jīng)常需要變化的細(xì)節(jié)分割出來,作為接口中的abstract方法然后面向接口來設(shè)計(jì)類。例5-14Pillar類將自己經(jīng)常需要變化的細(xì)節(jié)分離出來,作為接口Geometry中的抽象方法,然后面向接口Geometry來設(shè)計(jì)Pillar類,即Pillar類把Geometry定義的接口變量作為其中的成員,當(dāng)程序再增加一個(gè)實(shí)現(xiàn)接口Geometry的D類時(shí),接口變量所在的Pillar類不需要做任何修改,接口變量就可以回調(diào)D類實(shí)現(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可以回調(diào)類//實(shí)現(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方法,接口不可以。在設(shè)計(jì)程序中對(duì)抽象類和接口的選擇:(1)某個(gè)問題需要使用繼承,如除了需要實(shí)現(xiàn)父類的抽象方法,還需要從父類繼承一些變量或繼承一些重要的非抽象方法,需要考慮用抽象類。(2)某個(gè)問題不需要繼承,只需要若干個(gè)類給出某些重要的抽象方法的實(shí)現(xiàn)細(xì)節(jié),可以考慮用接口。返回5.15內(nèi)部類類可以有兩種重要的成員:成員變量和方法;類還可以有一種成員:內(nèi)部類。Java支持在一個(gè)類中聲明另一個(gè)類,這樣的類稱作內(nèi)部類,而包含內(nèi)部類的類成為內(nèi)部類的外嵌類。內(nèi)部類同類中聲明的方法或成員變量一樣,一個(gè)類把內(nèi)部類看作是自己的成員。外嵌類的成員變量在內(nèi)部類中仍然有效,內(nèi)部類中的方法也可以調(diào)用外嵌類中的方法。內(nèi)部類的類體中不可以聲明類變量和類方法。外嵌類可以用內(nèi)部類聲明對(duì)象,作為外嵌類的成員。例5-15給出了內(nèi)部類的用法返回classNorthEast{Stringland="黑土地";}classChina{intx=10,y=10;LiaoNingdalian;//內(nèi)部類聲明的對(duì)象作為外嵌類的成員

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

例5-15classLiaoNingextendsNorthEast{//內(nèi)部類的聲明

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

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

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

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

new類名或接口名(){……}(3)類名前面不能有修飾符。(4)類中不能定義構(gòu)造方法,因?yàn)樗鼪]有名字。也正是這個(gè)原因,在構(gòu)造對(duì)象時(shí),也不能帶參數(shù),因?yàn)槟J(rèn)構(gòu)造方法不能帶參數(shù)。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("這是匿名類中的方法");}}//匿名類類體結(jié)束

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

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

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

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

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論