Java編程思想第九章接口課件_第1頁
Java編程思想第九章接口課件_第2頁
Java編程思想第九章接口課件_第3頁
Java編程思想第九章接口課件_第4頁
Java編程思想第九章接口課件_第5頁
已閱讀5頁,還剩83頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第九章接口★

抽象方法和抽象類★接口★

策略設(shè)計(jì)模式和適配器設(shè)計(jì)模式第九章接口★抽象方法和抽象類19.1抽象類和抽象方法//P1691、抽象方法★

使用關(guān)鍵字abstract修飾的方法稱為抽象方法,

僅有方法聲明沒有方法體。2、抽象類★包含抽象方法的類稱為抽象類,必須也用abstract關(guān)鍵字聲明。用abstract關(guān)鍵字聲明的類一定是抽象類(無論類內(nèi)是否有抽象函數(shù))abstractclassInstrument{

abstractvoidplay();}9.1抽象類和抽象方法//P1691、抽象方法22.抽象類的性質(zhì)Ⅰ不能創(chuàng)建抽象類的對(duì)象,否則編譯器報(bào)錯(cuò)。但是可以創(chuàng)建抽象類的引用。Ⅱ如果繼承一個(gè)抽象類,沒有為基類中的所有抽象方法提供方法定義,那么這個(gè)導(dǎo)出類也是抽象類,必須也用abstract關(guān)鍵字聲明。3.抽象類的用途★抽象類為它的所有子類創(chuàng)建了一個(gè)通用接口,不同的子類使用不同的方式實(shí)現(xiàn)此接口2.抽象類的性質(zhì)3

abstractclassInstrument

{

//抽象類P170

publicabstractvoidplay(Noten);//抽象方法

publicStringwhat(){return“Instrument”;}publicabstractvoidadjust();

}//抽象類中可以包含非抽象方法,抽象函數(shù)不能是static和privateclassWindextendsInstrument{publicvoidplay(Noten){print("Wind.play()"+n);}publicStringwhat(){return"Wind";}publicvoidadjust(){}

}//子類實(shí)現(xiàn)抽象方法與覆蓋類似,可以使用協(xié)變返回類型,訪問權(quán)限可以相等或放松。abstractclassInstrument44、抽象類和抽象方法的典例4、抽象類和抽象方法的典例5publicclassMusic4{staticvoidtune(Instrumenti){i.play(Note.MIDDLE_C);}staticvoidtuneAll(Instrument[]e){for(Instrumenti:e)tune(i);} publicstaticvoidmain(String[]args){Instrument[]orch={newWind(),newPercussion(),newStringed(),newBrass(),newWoodwind()};tuneAll(orch);}}publicclassMusic4{69.2接口//P1721、接口(Interface)的概念★

Java中,用interface關(guān)鍵字來創(chuàng)建一個(gè)完全抽象的類◆區(qū)別:抽象類與接口2、接口的創(chuàng)建★接口是一種特殊的抽象類,但在創(chuàng)建時(shí)使用interface關(guān)鍵字,接口內(nèi)的方法不用加abstract關(guān)鍵字.3、interface的訪問權(quán)限控制有兩種:◆

缺省(包訪問權(quán)限控制)◆

public9.2接口//P1721、接口(Interfa74、接口的性質(zhì):1)只有抽象方法的聲明,不能有具體的方法實(shí)現(xiàn)

(不能有初始化語句塊)2)interface中所有方法的訪問權(quán)限都是public(缺省),否則編譯器報(bào)錯(cuò)3)接口也可以包含域,這些域隱式為public、static和final,必須進(jìn)行指定初始化。interfaceInstrument//P173{intVALUE=5;//static&final,指定初始化voidplay(Noten);//抽象函數(shù)缺省為publicvoidadjust();

}4、接口的性質(zhì):85、接口的實(shí)現(xiàn)

要讓一個(gè)類實(shí)現(xiàn)某個(gè)接口或者一組接口需要使用implements關(guān)鍵字,實(shí)現(xiàn)接口的類必須實(shí)現(xiàn)接口中所有的抽象方法,并且訪問權(quán)限必須明確是public。

classWind

implementsInstrument{ //接口抽象方法的具體實(shí)現(xiàn)

publicvoidplay(Noten)

{print(this+“.play()”+n);}

publicvoidadjust()

{print(this+“.adjust()”);}publicStringtoString()

{return“Wind”;}}5、接口的實(shí)現(xiàn)9Java編程思想第九章接口課件10//這兩個(gè)子類也實(shí)現(xiàn)了Instrument接口classWoodwindextendsWind{publicStringtoString(){return"Woodwind";}}classBrassextendsWind{publicStringtoString(){return"Brass";}} //這兩個(gè)子類也實(shí)現(xiàn)了Instrument接口11publicclassMusic5{staticvoidtune(Instrumenti)

//i是指向?qū)崿F(xiàn)了Instrument接口的類對(duì)象的引用

{i.play(Note.MIDDLE_C);}staticvoidtuneAll(Instrument[]e)

{for(Instrumenti:e)

tune(i);

}publicstaticvoidmain(String[]args)

{Instrument[]orch={newWind(),newPercussion(),newStringed(),newBrass(),newWoodwind();}

//向上轉(zhuǎn)型為稱為Instrument的接口

tuneAll(orch);

}}

publicclassMusic512★歸納:向上轉(zhuǎn)型語義的拓展1)向上轉(zhuǎn)型為稱為Instrument的普通類2)向上轉(zhuǎn)型為稱為Instrument的抽象類向上轉(zhuǎn)型為稱為Instrument的接口6、接口的作用◆

Java不支持多重繼承★

Interface的主要作用在于:利用接口來實(shí)現(xiàn)類似多重繼承的機(jī)制★歸納:向上轉(zhuǎn)型語義的拓展13◆接口與抽象類有即相似的地方,又有太多區(qū)別。1、抽象類相對(duì)于接口的優(yōu)點(diǎn)⑴抽象類可以提供某些方法的部分實(shí)現(xiàn),然而接口不可以如果向一個(gè)抽象類中加入一個(gè)新的方法,那么它所有的子類都得到了這個(gè)新方法而接口卻做不到這一點(diǎn):如果向一個(gè)接口中加入一個(gè)新方法,只能是抽象的,所有實(shí)現(xiàn)這個(gè)接口的類都必須新增加對(duì)這個(gè)方法實(shí)現(xiàn)三、缺省適配模式◆接口與抽象類有即相似的地方,又有太多區(qū)別。三、缺省142、接口相對(duì)于抽象類的優(yōu)點(diǎn)⑴接口的最大優(yōu)點(diǎn)是實(shí)現(xiàn)了多重繼承的機(jī)制★接口的這個(gè)優(yōu)點(diǎn)卻是繼承的一個(gè)致命缺陷

◆由于Java語言的單繼承性,如果一個(gè)類也想具有這個(gè)抽象類的功能,只能加入到該繼承樹中,這樣抽象類作為類型定義工具的效能大打折扣2、接口相對(duì)于抽象類的優(yōu)點(diǎn)15★在這點(diǎn)上,接口的優(yōu)勢(shì)就顯現(xiàn)出來了◆任何一個(gè)實(shí)現(xiàn)了一個(gè)接口所規(guī)定的方法的類,都可以具有這個(gè)接口的類型◆而一個(gè)類可以實(shí)現(xiàn)任意多個(gè)接口,從而這個(gè)類就具有了多種類型(不像抽象類,后者如果想具有某種類型就必須加入到某一棵繼承樹中)★在這點(diǎn)上,接口的優(yōu)勢(shì)就顯現(xiàn)出來了163、結(jié)合抽象類和接口的各自優(yōu)勢(shì),經(jīng)典的設(shè)計(jì)模式就出來了:★

聲明類型的工作仍由接口承擔(dān),但是同時(shí)給出一個(gè)Java抽象類,聲明實(shí)現(xiàn)了這個(gè)接口,(可以不實(shí)現(xiàn)接口中的公有抽象函數(shù))◆

而其他同屬于這個(gè)接口類型的具體類可選擇實(shí)現(xiàn)這個(gè)接口,也可選擇繼承這個(gè)抽象類歸納:◆在類的層次結(jié)構(gòu)中,接口在最上面,然后緊跟著抽象類,這樣接口和抽象類的最大優(yōu)點(diǎn)都能發(fā)揮到極至◆這就是缺省適配模式3、結(jié)合抽象類和接口的各自優(yōu)勢(shì),經(jīng)典的設(shè)計(jì)模式就出來了:17四、適配器設(shè)計(jì)模式1、適配器(Adapter)的概念★適配器類:也稱為類型轉(zhuǎn)換器,基于現(xiàn)有類的功能,向客戶提供類型轉(zhuǎn)換。2、適配器的實(shí)現(xiàn)之一:類適配器⑴開發(fā)人員要實(shí)現(xiàn)一個(gè)完成整數(shù)的求和操作的接口:★public

interfaceOperation{

//只有方法的聲明而并沒有實(shí)現(xiàn)

int

add(int

a,int

b);}四、適配器設(shè)計(jì)模式1、適配器(Adapter)的概念18⑵★在仔細(xì)了解這個(gè)接口的定義后,開發(fā)人員終于發(fā)現(xiàn)了一個(gè)第三方類OtherAdd,里面有一個(gè)方法otheradd能實(shí)現(xiàn)期望的功能,說明如下:◆

public

class

OtherAdd{

public

int

otheradd(int

a,int

b)

{

return

a

+

b;}

}

⑵★在仔細(xì)了解這個(gè)接口的定義后,開發(fā)人員終于發(fā)現(xiàn)了一個(gè)第19⑶利用OtherAdd類的otheradd方法,進(jìn)而實(shí)現(xiàn)客戶的Operation接口中的Add方法,讓這個(gè)第三方類來為客戶提供他們期望的服務(wù),避免開發(fā)人員再度去研究類似方法的實(shí)現(xiàn),就是用類適配器模式:

public

class

AdapterOperation

extends

OtherAdd

implements

Operation{

public

int

add(int

a,int

b){

return

otheradd(a,b);}

}

⑶利用OtherAdd類的otheradd方法,進(jìn)而20⑷以上實(shí)現(xiàn)中存在的三種角色分別是:★適配源(Adaptee):OtherAdd★適配目標(biāo)(Object):Operation★適配器(Adapter):AdapterOperation◆適配器的主要工作就是通過封裝已有的功能,使它能夠提供接口的實(shí)現(xiàn)⑷以上實(shí)現(xiàn)中存在的三種角色分別是:21五、適配器設(shè)計(jì)模式3、適配器的實(shí)現(xiàn)之二:對(duì)象適配器⑴假如客戶接口期望的功能不止一個(gè),而是多個(gè):★public

interface

Operation{

public

int

add(int

a,int

b);

public

int

minus(int

a,int

b);//減法

}

五、適配器設(shè)計(jì)模式3、適配器的實(shí)現(xiàn)之二:對(duì)象適配器22⑵而能提供這些實(shí)現(xiàn)的源可能不止一個(gè):★public

classOtherAdd{

public

int

otheradd(int

a,int

b){

return

a

+

b;}

}

public

class

OtherMinus

{

public

int

otherminus(int

a,int

b)

{

return

a

-

b;}

}

由于Java不支持多重繼承,所以不能像上面一樣,通過構(gòu)建一個(gè)適配器,讓它來繼承所有的源以完成我們的期望?!衾眠m配器的另一種實(shí)現(xiàn):對(duì)象適配器⑵而能提供這些實(shí)現(xiàn)的源可能不止一個(gè):23public

class

AdapterOperation

implements

Operation{private

OtherAdd

add=newOtherAdd();private

OtherMinus

minus=newOtherMinus

();

public

int

add(int

a,int

b)

//適配加法運(yùn)算

{return

add.otheradd(a,b);}

public

int

minus(int

a,int

b)

//適配減法運(yùn)算

{return

minus.otherminus(a,b);}}上面代碼很明顯,適配器并不是通過繼承來獲取適配類源功能的,而是通過適配類的對(duì)象來獲取的,這就解決了Java不能多重繼承所帶來的不便這也回到了Java提倡的編程思想:盡量使用組合,而不要使用繼承public

class

AdapterOperatio24★

importjava.util.Arrays;classProcessor//處理器P175

{ Objectprocess(Objectinput){……}}classUpcaseextendsProcessor{//協(xié)變返回類型的覆蓋

Stringprocess(Objectinput)

{return((String)input).toUpperCase();}}★importjava.util.Arrays;25★

classDowncaseextendsProcessor//小寫處理器

{//協(xié)變返回類型的覆蓋

Stringprocess(Objectinput)

{return((String)input).toLowerCase();}}classSplitterextendsProcessor//分割器

{//協(xié)變返回類型的覆蓋

Stringprocess(Objectinput)

{returnArrays.toString(((String)input).split(“”));}}//字符串分割放在數(shù)組中再通過toString方法轉(zhuǎn)換為字符串//“zsdcv“轉(zhuǎn)化為[zsd,c,v]★classDowncaseextendsP26★publicclassApply{//注意該方法的兩個(gè)參數(shù)publicstaticvoidprocess

(Processorp,Objects){

print(

cess(s));}

publicstaticvoidmain(String[

]args){//在參數(shù)傳遞的過程中,發(fā)生向上轉(zhuǎn)型process(newUpcase(),”abcd”);

process(newSplitter(),”abcd”);

}}Acess()方法和Processor之間的耦合過緊,這使得很難復(fù)用Acess()代碼.★publicclassApply27六、完全解耦P1741、完全解耦的概念和基本思想接口可以應(yīng)用于多種不同的具體類型,利用接口將功能從具體的類型中解耦出來,代碼也就更具有可復(fù)用性2、回到Processor類和Apply類中的問題★在前面提到:Acess()中的代碼很難復(fù)用◆通過下面例子分析:為什么很難復(fù)用六、完全解耦P1741、完全解耦的概念和基本思想228★

classFilter//濾波器Filter結(jié)構(gòu)與Processor相似具有相同的接口元素

{publicWaveform

process(Waveforminput)

{……}}

classLowPassextendsFilter//低通濾波器

{publicWaveform

process(Waveforminput)

{……}}classHighPassextendsFilter{...}//高通濾波器classBandPassextendsFilter{...}//帶通濾波器//Acess(Processorp,Objects)不能以Filter對(duì)象引用為參數(shù)★classFilter//濾波器Filter結(jié)29★分析:代碼不能復(fù)用的原因◆

Filter與Processor具有相同的接口元素,但是它并非繼承自Processor?!鬚rocessor與Acess方法的結(jié)合異常緊密,因此不能將Filter用于Acess方法3、復(fù)用代碼的第一種方式:★

將Processor抽象為接口,客戶端程序員遵循該接口來編寫他們自己的類,讓process函數(shù)的功能和具體的類型分離★分析:代碼不能復(fù)用的原因30publicinterfaceProcessor{

Objectprocess(Objectinput);}publicclassApply//將Acess與Processor的耦合關(guān)系解開{publicstaticvoidprocess(Processorp,Objects){System.out.println(cess(s));}}publicinterfaceProcessor31publicabstract

class

StringProcessor

implementsProcessor{//協(xié)變返回,因?yàn)槭浅橄箢恜rocess方法可以不實(shí)現(xiàn)!publicabstractStringprocess(Objectinput);

}//缺省適配模式classUpcaseextendsStringProcessor{//實(shí)現(xiàn)對(duì)Pcess的覆蓋

publicStringprocess(Objectinput)

{return((String)input).toUpperCase();}}classDowncaseextendsStringProcessor{...}classSplitterextendsStringProcessor{...}publicabstractclassStrin32★分析:◆因?yàn)榇嬖诶^承、覆蓋(通過協(xié)變返回實(shí)現(xiàn))和向上轉(zhuǎn)型(這里向上轉(zhuǎn)型為Processor接口)所以,程序?qū)崿F(xiàn)了多態(tài),即動(dòng)態(tài)綁定◆這里的多態(tài)比前面例子更為復(fù)雜★分析:33六、完全解耦4、復(fù)用代碼的第二種方式:在有些情況下,類是被發(fā)現(xiàn)而不是被創(chuàng)建的,這時(shí)不能再使用第一種方法★解決方案:使用對(duì)象適配器分析:這個(gè)例子同上面程序的區(qū)別在于◆本例中的Filter和LowPass等類是已經(jīng)定義好的◆我們要做的事情是:根據(jù)現(xiàn)有類的功能,設(shè)計(jì)出一個(gè)對(duì)象適配器將Filter與Processor聯(lián)系起來,使之滿足設(shè)計(jì)人員的需求六、完全解耦4、復(fù)用代碼的第二種方式:34★

classFilterAdapterimplementsProcessor

{

Filterf;//對(duì)象適配器

publicFilterAdapter(Filterf)

{this.f=f;}

publicWaveformprocess(Objectinput)

{cess((Waveform)input);}}classFilter{publicWaveformprocess(Waveforminput)

{...….;}}classLowPassextendsFilter{...}★classFilterAdapterimple35//Acess(newFilterAdapter(newLowPass()),w);//Acess(newFilterAd369.4、Java中的多重繼承P1781、基本原則★

Java不支持多重繼承,而是使用多重接口來實(shí)現(xiàn)類似多重繼承的機(jī)制2、多重接口的定義★

class類名

extends基類implements接口1,...接口n◆

注意:

繼承父類在前,實(shí)現(xiàn)接口在后。派生類能向上轉(zhuǎn)型為多個(gè)基類型或接口類型。9.4、Java中的多重繼承P1781、基本原則37★

interfaceCanFight{voidfight();}//P179interfaceCanSwim{voidswim();}classActionCharacter//動(dòng)作演員{publicvoidfight(){}}classHero

extendsActionCharacterimplementsCanFight,CanSwim

{publicvoidswim(){}}publicclassAdventure{publicstaticvoidt(CanFightx){x.fight();}publicstaticvoidu(CanSwimx){x.swim();}publicstaticvoidw(ActionCharacterx){x.fight();}publicstaticvoidmain(String[]args){Heroh=newHero();t(h);u(h);w(h);}}★interfaceCanFight{voi389.5、通過繼承來擴(kuò)展接口//p180接口也可繼承,在子接口中添加了父接口的方法聲明interfaceMonster{voidmenace();}//怪物\威脅

interfaceDangerousMonsterextendsMonster

{voiddestroy();}interfaceLethal{voidkill();}//致命

interfaceVampireextendsDangerousMonster,Lethal

{voiddrinkBlood();}//該語法僅用于接口繼承classVeryBadVampireimplementsVampire{publicvoidmenace(){}publicvoiddestroy(){}publicvoidkill(){}publicvoiddrinkBlood(){}}

9.5、通過繼承來擴(kuò)展接口//p180接口也可繼承,在39publicclassHorrorShow{staticvoidu(Monsterb){b.menace();}staticvoidv(DangerousMonsterd){d.menace();d.destroy();}staticvoidw(Lethall){l.kill();}publicstaticvoidmain(String[]args){Vampirevlad=newVeryBadVampire();u(vlad);v(vlad);w(vlad);}}publicclassHorrorShow{409.51組合接口時(shí)的名字沖突P181interfaceI1{voidf();}interfaceI2{intf(inti);}interfaceI3{intf();}classC{publicintf(){return1;}}classC2implementsI1,I2{publicvoidf(){}publicintf(inti){return1;}//overloaded}classC4extendsCimplementsI3{publicintf(){return2;}}//!classC5extendsCimplementsI1{}//!interfaceI4extendsI1,I3{}///:~組合不同的接口中含有相同的方法名時(shí)可能會(huì)產(chǎn)生二義性9.51組合接口時(shí)的名字沖突P181interfac419.7、接口中的域P183★

接口中的域隱式是static和final的(P184,習(xí)題17),可以被非常量表達(dá)式初始化?!?/p>

JavaSE5以后的版本提供了功能更加強(qiáng)大和靈活的enum關(guān)鍵字,因此通過接口來群組常量已經(jīng)沒有什么意義9.7、接口中的域P183★接口中的域隱式是s42十、嵌套接口1、接口嵌套在類中★

classA{interfaceB{voidf();}.....2、接口嵌套在其它接口中★

interfaceE{interfaceG{voidf();}.....十、嵌套接口1、接口嵌套在類中43習(xí)題★

P171習(xí)題2P174習(xí)題5P180習(xí)題13P184習(xí)題17習(xí)題★P171習(xí)題244第九章接口★

抽象方法和抽象類★接口★

策略設(shè)計(jì)模式和適配器設(shè)計(jì)模式第九章接口★抽象方法和抽象類459.1抽象類和抽象方法//P1691、抽象方法★

使用關(guān)鍵字abstract修飾的方法稱為抽象方法,

僅有方法聲明沒有方法體。2、抽象類★包含抽象方法的類稱為抽象類,必須也用abstract關(guān)鍵字聲明。用abstract關(guān)鍵字聲明的類一定是抽象類(無論類內(nèi)是否有抽象函數(shù))abstractclassInstrument{

abstractvoidplay();}9.1抽象類和抽象方法//P1691、抽象方法462.抽象類的性質(zhì)Ⅰ不能創(chuàng)建抽象類的對(duì)象,否則編譯器報(bào)錯(cuò)。但是可以創(chuàng)建抽象類的引用。Ⅱ如果繼承一個(gè)抽象類,沒有為基類中的所有抽象方法提供方法定義,那么這個(gè)導(dǎo)出類也是抽象類,必須也用abstract關(guān)鍵字聲明。3.抽象類的用途★抽象類為它的所有子類創(chuàng)建了一個(gè)通用接口,不同的子類使用不同的方式實(shí)現(xiàn)此接口2.抽象類的性質(zhì)47

abstractclassInstrument

{

//抽象類P170

publicabstractvoidplay(Noten);//抽象方法

publicStringwhat(){return“Instrument”;}publicabstractvoidadjust();

}//抽象類中可以包含非抽象方法,抽象函數(shù)不能是static和privateclassWindextendsInstrument{publicvoidplay(Noten){print("Wind.play()"+n);}publicStringwhat(){return"Wind";}publicvoidadjust(){}

}//子類實(shí)現(xiàn)抽象方法與覆蓋類似,可以使用協(xié)變返回類型,訪問權(quán)限可以相等或放松。abstractclassInstrument484、抽象類和抽象方法的典例4、抽象類和抽象方法的典例49publicclassMusic4{staticvoidtune(Instrumenti){i.play(Note.MIDDLE_C);}staticvoidtuneAll(Instrument[]e){for(Instrumenti:e)tune(i);} publicstaticvoidmain(String[]args){Instrument[]orch={newWind(),newPercussion(),newStringed(),newBrass(),newWoodwind()};tuneAll(orch);}}publicclassMusic4{509.2接口//P1721、接口(Interface)的概念★

Java中,用interface關(guān)鍵字來創(chuàng)建一個(gè)完全抽象的類◆區(qū)別:抽象類與接口2、接口的創(chuàng)建★接口是一種特殊的抽象類,但在創(chuàng)建時(shí)使用interface關(guān)鍵字,接口內(nèi)的方法不用加abstract關(guān)鍵字.3、interface的訪問權(quán)限控制有兩種:◆

缺省(包訪問權(quán)限控制)◆

public9.2接口//P1721、接口(Interfa514、接口的性質(zhì):1)只有抽象方法的聲明,不能有具體的方法實(shí)現(xiàn)

(不能有初始化語句塊)2)interface中所有方法的訪問權(quán)限都是public(缺省),否則編譯器報(bào)錯(cuò)3)接口也可以包含域,這些域隱式為public、static和final,必須進(jìn)行指定初始化。interfaceInstrument//P173{intVALUE=5;//static&final,指定初始化voidplay(Noten);//抽象函數(shù)缺省為publicvoidadjust();

}4、接口的性質(zhì):525、接口的實(shí)現(xiàn)

要讓一個(gè)類實(shí)現(xiàn)某個(gè)接口或者一組接口需要使用implements關(guān)鍵字,實(shí)現(xiàn)接口的類必須實(shí)現(xiàn)接口中所有的抽象方法,并且訪問權(quán)限必須明確是public。

classWind

implementsInstrument{ //接口抽象方法的具體實(shí)現(xiàn)

publicvoidplay(Noten)

{print(this+“.play()”+n);}

publicvoidadjust()

{print(this+“.adjust()”);}publicStringtoString()

{return“Wind”;}}5、接口的實(shí)現(xiàn)53Java編程思想第九章接口課件54//這兩個(gè)子類也實(shí)現(xiàn)了Instrument接口classWoodwindextendsWind{publicStringtoString(){return"Woodwind";}}classBrassextendsWind{publicStringtoString(){return"Brass";}} //這兩個(gè)子類也實(shí)現(xiàn)了Instrument接口55publicclassMusic5{staticvoidtune(Instrumenti)

//i是指向?qū)崿F(xiàn)了Instrument接口的類對(duì)象的引用

{i.play(Note.MIDDLE_C);}staticvoidtuneAll(Instrument[]e)

{for(Instrumenti:e)

tune(i);

}publicstaticvoidmain(String[]args)

{Instrument[]orch={newWind(),newPercussion(),newStringed(),newBrass(),newWoodwind();}

//向上轉(zhuǎn)型為稱為Instrument的接口

tuneAll(orch);

}}

publicclassMusic556★歸納:向上轉(zhuǎn)型語義的拓展1)向上轉(zhuǎn)型為稱為Instrument的普通類2)向上轉(zhuǎn)型為稱為Instrument的抽象類向上轉(zhuǎn)型為稱為Instrument的接口6、接口的作用◆

Java不支持多重繼承★

Interface的主要作用在于:利用接口來實(shí)現(xiàn)類似多重繼承的機(jī)制★歸納:向上轉(zhuǎn)型語義的拓展57◆接口與抽象類有即相似的地方,又有太多區(qū)別。1、抽象類相對(duì)于接口的優(yōu)點(diǎn)⑴抽象類可以提供某些方法的部分實(shí)現(xiàn),然而接口不可以如果向一個(gè)抽象類中加入一個(gè)新的方法,那么它所有的子類都得到了這個(gè)新方法而接口卻做不到這一點(diǎn):如果向一個(gè)接口中加入一個(gè)新方法,只能是抽象的,所有實(shí)現(xiàn)這個(gè)接口的類都必須新增加對(duì)這個(gè)方法實(shí)現(xiàn)三、缺省適配模式◆接口與抽象類有即相似的地方,又有太多區(qū)別。三、缺省582、接口相對(duì)于抽象類的優(yōu)點(diǎn)⑴接口的最大優(yōu)點(diǎn)是實(shí)現(xiàn)了多重繼承的機(jī)制★接口的這個(gè)優(yōu)點(diǎn)卻是繼承的一個(gè)致命缺陷

◆由于Java語言的單繼承性,如果一個(gè)類也想具有這個(gè)抽象類的功能,只能加入到該繼承樹中,這樣抽象類作為類型定義工具的效能大打折扣2、接口相對(duì)于抽象類的優(yōu)點(diǎn)59★在這點(diǎn)上,接口的優(yōu)勢(shì)就顯現(xiàn)出來了◆任何一個(gè)實(shí)現(xiàn)了一個(gè)接口所規(guī)定的方法的類,都可以具有這個(gè)接口的類型◆而一個(gè)類可以實(shí)現(xiàn)任意多個(gè)接口,從而這個(gè)類就具有了多種類型(不像抽象類,后者如果想具有某種類型就必須加入到某一棵繼承樹中)★在這點(diǎn)上,接口的優(yōu)勢(shì)就顯現(xiàn)出來了603、結(jié)合抽象類和接口的各自優(yōu)勢(shì),經(jīng)典的設(shè)計(jì)模式就出來了:★

聲明類型的工作仍由接口承擔(dān),但是同時(shí)給出一個(gè)Java抽象類,聲明實(shí)現(xiàn)了這個(gè)接口,(可以不實(shí)現(xiàn)接口中的公有抽象函數(shù))◆

而其他同屬于這個(gè)接口類型的具體類可選擇實(shí)現(xiàn)這個(gè)接口,也可選擇繼承這個(gè)抽象類歸納:◆在類的層次結(jié)構(gòu)中,接口在最上面,然后緊跟著抽象類,這樣接口和抽象類的最大優(yōu)點(diǎn)都能發(fā)揮到極至◆這就是缺省適配模式3、結(jié)合抽象類和接口的各自優(yōu)勢(shì),經(jīng)典的設(shè)計(jì)模式就出來了:61四、適配器設(shè)計(jì)模式1、適配器(Adapter)的概念★適配器類:也稱為類型轉(zhuǎn)換器,基于現(xiàn)有類的功能,向客戶提供類型轉(zhuǎn)換。2、適配器的實(shí)現(xiàn)之一:類適配器⑴開發(fā)人員要實(shí)現(xiàn)一個(gè)完成整數(shù)的求和操作的接口:★public

interfaceOperation{

//只有方法的聲明而并沒有實(shí)現(xiàn)

int

add(int

a,int

b);}四、適配器設(shè)計(jì)模式1、適配器(Adapter)的概念62⑵★在仔細(xì)了解這個(gè)接口的定義后,開發(fā)人員終于發(fā)現(xiàn)了一個(gè)第三方類OtherAdd,里面有一個(gè)方法otheradd能實(shí)現(xiàn)期望的功能,說明如下:◆

public

class

OtherAdd{

public

int

otheradd(int

a,int

b)

{

return

a

+

b;}

}

⑵★在仔細(xì)了解這個(gè)接口的定義后,開發(fā)人員終于發(fā)現(xiàn)了一個(gè)第63⑶利用OtherAdd類的otheradd方法,進(jìn)而實(shí)現(xiàn)客戶的Operation接口中的Add方法,讓這個(gè)第三方類來為客戶提供他們期望的服務(wù),避免開發(fā)人員再度去研究類似方法的實(shí)現(xiàn),就是用類適配器模式:

public

class

AdapterOperation

extends

OtherAdd

implements

Operation{

public

int

add(int

a,int

b){

return

otheradd(a,b);}

}

⑶利用OtherAdd類的otheradd方法,進(jìn)而64⑷以上實(shí)現(xiàn)中存在的三種角色分別是:★適配源(Adaptee):OtherAdd★適配目標(biāo)(Object):Operation★適配器(Adapter):AdapterOperation◆適配器的主要工作就是通過封裝已有的功能,使它能夠提供接口的實(shí)現(xiàn)⑷以上實(shí)現(xiàn)中存在的三種角色分別是:65五、適配器設(shè)計(jì)模式3、適配器的實(shí)現(xiàn)之二:對(duì)象適配器⑴假如客戶接口期望的功能不止一個(gè),而是多個(gè):★public

interface

Operation{

public

int

add(int

a,int

b);

public

int

minus(int

a,int

b);//減法

}

五、適配器設(shè)計(jì)模式3、適配器的實(shí)現(xiàn)之二:對(duì)象適配器66⑵而能提供這些實(shí)現(xiàn)的源可能不止一個(gè):★public

classOtherAdd{

public

int

otheradd(int

a,int

b){

return

a

+

b;}

}

public

class

OtherMinus

{

public

int

otherminus(int

a,int

b)

{

return

a

-

b;}

}

由于Java不支持多重繼承,所以不能像上面一樣,通過構(gòu)建一個(gè)適配器,讓它來繼承所有的源以完成我們的期望。◆利用適配器的另一種實(shí)現(xiàn):對(duì)象適配器⑵而能提供這些實(shí)現(xiàn)的源可能不止一個(gè):67public

class

AdapterOperation

implements

Operation{private

OtherAdd

add=newOtherAdd();private

OtherMinus

minus=newOtherMinus

();

public

int

add(int

a,int

b)

//適配加法運(yùn)算

{return

add.otheradd(a,b);}

public

int

minus(int

a,int

b)

//適配減法運(yùn)算

{return

minus.otherminus(a,b);}}上面代碼很明顯,適配器并不是通過繼承來獲取適配類源功能的,而是通過適配類的對(duì)象來獲取的,這就解決了Java不能多重繼承所帶來的不便這也回到了Java提倡的編程思想:盡量使用組合,而不要使用繼承public

class

AdapterOperatio68★

importjava.util.Arrays;classProcessor//處理器P175

{ Objectprocess(Objectinput){……}}classUpcaseextendsProcessor{//協(xié)變返回類型的覆蓋

Stringprocess(Objectinput)

{return((String)input).toUpperCase();}}★importjava.util.Arrays;69★

classDowncaseextendsProcessor//小寫處理器

{//協(xié)變返回類型的覆蓋

Stringprocess(Objectinput)

{return((String)input).toLowerCase();}}classSplitterextendsProcessor//分割器

{//協(xié)變返回類型的覆蓋

Stringprocess(Objectinput)

{returnArrays.toString(((String)input).split(“”));}}//字符串分割放在數(shù)組中再通過toString方法轉(zhuǎn)換為字符串//“zsdcv“轉(zhuǎn)化為[zsd,c,v]★classDowncaseextendsP70★publicclassApply{//注意該方法的兩個(gè)參數(shù)publicstaticvoidprocess

(Processorp,Objects){

print(

cess(s));}

publicstaticvoidmain(String[

]args){//在參數(shù)傳遞的過程中,發(fā)生向上轉(zhuǎn)型process(newUpcase(),”abcd”);

process(newSplitter(),”abcd”);

}}Acess()方法和Processor之間的耦合過緊,這使得很難復(fù)用Acess()代碼.★publicclassApply71六、完全解耦P1741、完全解耦的概念和基本思想接口可以應(yīng)用于多種不同的具體類型,利用接口將功能從具體的類型中解耦出來,代碼也就更具有可復(fù)用性2、回到Processor類和Apply類中的問題★在前面提到:Acess()中的代碼很難復(fù)用◆通過下面例子分析:為什么很難復(fù)用六、完全解耦P1741、完全解耦的概念和基本思想272★

classFilter//濾波器Filter結(jié)構(gòu)與Processor相似具有相同的接口元素

{publicWaveform

process(Waveforminput)

{……}}

classLowPassextendsFilter//低通濾波器

{publicWaveform

process(Waveforminput)

{……}}classHighPassextendsFilter{...}//高通濾波器classBandPassextendsFilter{...}//帶通濾波器//Acess(Processorp,Objects)不能以Filter對(duì)象引用為參數(shù)★classFilter//濾波器Filter結(jié)73★分析:代碼不能復(fù)用的原因◆

Filter與Processor具有相同的接口元素,但是它并非繼承自Processor?!鬚rocessor與Acess方法的結(jié)合異常緊密,因此不能將Filter用于Acess方法3、復(fù)用代碼的第一種方式:★

將Processor抽象為接口,客戶端程序員遵循該接口來編寫他們自己的類,讓process函數(shù)的功能和具體的類型分離★分析:代碼不能復(fù)用的原因74publicinterfaceProcessor{

Objectprocess(Objectinput);}publicclassApply//將Acess與Processor的耦合關(guān)系解開{publicstaticvoidprocess(Processorp,Objects){System.out.println(cess(s));}}publicinterfaceProcessor75publicabstract

class

StringProcessor

implementsProcessor{//協(xié)變返回,因?yàn)槭浅橄箢恜rocess方法可以不實(shí)現(xiàn)!publicabstractStringprocess(Objectinput);

}//缺省適配模式classUpcaseextendsStringProcessor{//實(shí)現(xiàn)對(duì)Pcess的覆蓋

publicStringprocess(Objectinput)

{return((String)input).toUpperCase();}}classDowncaseextendsStringProcessor{...}classSplitterextendsStringProcessor{...}publicabstractclassStrin76★分析:◆因?yàn)榇嬖诶^承、覆蓋(通過協(xié)變返回實(shí)現(xiàn))和向上轉(zhuǎn)型(這里向上轉(zhuǎn)型為Processor接口)所以,程序?qū)崿F(xiàn)了多態(tài),即動(dòng)態(tài)綁定◆這里的多態(tài)比前面例子更為復(fù)雜★分析:77六、完全解耦4、復(fù)用代碼的第二種方式:在有些情況下,類是被發(fā)現(xiàn)而不是被創(chuàng)建的,這時(shí)不能再使用第一種方法★解決方案:使用對(duì)象適配器分析:這個(gè)例子同上面程序的區(qū)別在于◆本例中的Filter和LowPass等類是已經(jīng)定義好的◆我們要做的事情是:根據(jù)現(xiàn)有類的功能,設(shè)計(jì)出一個(gè)對(duì)象適配器將Filter與Processor聯(lián)系起來,使之滿足設(shè)計(jì)人員的需求六、完全解耦4、復(fù)用代碼的第二種方式:78★

classFilterAdapterimplementsProcessor

{

Filterf;//對(duì)象適配器

publicFilterAdapter(Filterf)

{this.f=f;}

publicWaveformprocess(Objectinput)

{cess((Waveform)input);}}classFilter{publicWaveformprocess(Waveforminput)

{...….;}}classLowPassextendsFilter{...}★classFilterAdapterimple79//Acess(newFilterAdapter(newLowPass()),w);//Acess(newFilterAd809.4、Java中的多重繼承P1781、基本原則★

Java不支持多重繼承,而

溫馨提示

  • 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)論