版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 拍攝合同范例3篇
- 各種物品寄售合同范例
- 國(guó)際招標(biāo)貨物合同范例
- 亮化出租維修合同范例
- 日文勞務(wù)合同范例
- 漁網(wǎng)加工銷售合同范例
- 墻體內(nèi)粉刷合同范例
- 三基護(hù)理考試題與參考答案
- 急救理論知識(shí)考試模擬題(附答案)
- 債權(quán)擔(dān)保協(xié)議合同范例
- 北京開放大學(xué)《自動(dòng)控制技術(shù)及應(yīng)用》終結(jié)性考試復(fù)習(xí)題庫(附答案)
- 高中高一級(jí)部拔河比賽活動(dòng)實(shí)施方案
- 每日食品安全檢查記錄
- 航空機(jī)務(wù)專業(yè)職業(yè)生涯規(guī)劃書
- 八年級(jí)英語上學(xué)期期末考試(深圳卷)-2023-2024學(xué)年八年級(jí)英語上冊(cè)單元重難點(diǎn)易錯(cuò)題精練(牛津深圳版)
- 項(xiàng)目成本節(jié)約措施總結(jié)報(bào)告
- 迎元旦趣味活動(dòng)及知識(shí)競(jìng)賽試題及答案
- SH/T 3543-2007 石油化工建設(shè)工程項(xiàng)目施工過程技術(shù)文件規(guī)定
- 減鹽控油控制體重規(guī)章制度
- 建筑之歌課件PPT
- (完整版)員工流失文獻(xiàn)綜述
評(píng)論
0/150
提交評(píng)論