天天看小說

第226章

大B:“靜態分派,動態分派,多分派,單分派是visitor模式準備。”

小A:“visitor模式準備?能不能詳細講講,我不明白。”

大B:“可以。”

1、靜態分派:

(1)定義:發生在編譯時期,分派根據靜態類型信息發生,重載就是靜態分派。

(2)什麼是靜態類型:變量被聲明時的類型是靜態類型。

什麼是動態類型:變量所引用的對象的真實類型。

(3)有兩個類,BlackCat,WhiteCat都繼承自。

如下調用

classCat{}

classWhiteCatextendsCat{}

classBlackCatextendsCat{}

publicclassPerson{

publicvoidfeed(Catcat){

System.out.println(“feedcat”);

}

publicvoidfeed(WhiteCatcat){

System.out.println(“feedWhiteCat”);

}

publicvoidfeed(BlackCatcat){

System.out.println(“feedBlackCat”);

}

publicstaticvoidmain(String[]args){

Catwc=newWhiteCat();

Catbc=newBlackCat();

Personp=newPerson();

p.feed(wc);

p.feed(bc);

}

}

運行結果是:

feedcat

feedcat

這樣的結果是因爲重載是靜態分派,在編譯器執行的,取決於變量的聲明類型,因爲wc,bc都是Cat所以調用的都是feed(Catcat)的函數。

2、動態分派

定義:發生在運行期,動態分派,動態的置換掉某個方法。

還是上面類似的例子:

classCat{

publicvoideat(){

System.out.println(“cateat”);

}

}

publicclassBlackCatextendsCat{

publicvoideat(){

System.out.println(“blackcateat”);

}

publicstaticvoidmain(String[]args){

Catcat=newBlackCat();

cat.eat();

}

}這個時候的結果是:

blackcateat

這樣的結果是因爲在執行期發生了向下轉型,就是動態分派了。

3、單分派:

定義:根據一個宗量的類型進行方法的選擇。

4、多分派:

(1)定義:根據多於一個宗量的類型對方法的選擇。

(2)說明:多分派其實是一系列的單分派組成的,區別的地方就是這些但分派不能分割。

(3)Java是動態單分派,靜態多分派語言。

大B:“訪問同一類型的集合類是我們最常見的事情了,我們工作中這樣的代碼太常見了。”

Iteratorie=list.iterator();

while(ie.hasNext()){

Person

p=(Person)ie.next();

p.doWork();

}

這種訪問的特點是集合類中的對象是同一類對象Person,他們擁有功能的方法run,我們調用的恰好是這個共同的方法。在大部份的情況下,這個是可以的,但在一些複雜的情況,如被訪問者的繼承結構複雜,被訪問者的並不是同一類對象,也就是說不是繼承自同一個根類。方法名也並不相同。例如JavaGUI中的事件就是一個例子。

例如這樣的問題,有如下類和方法:

類:PA,方法:runPA();

類:PB,方法:runPB();

類:PC,方法:runPC();

類:PD,方法:runPD();

類:PE,方法:runPE();

有一個集合類。

Listlist=newArrayList();

list.add(newPA());

list.add(newPB());

list.add(newPC());

list.add(newPD());

list.add(newPE());

……

大B:“要求能訪問到每個類的對應的方法。我們第一反應應該是這樣的。”

Iteratorie=list.iterator();

while(ie.hasNext()){

Objectobj=ie.next();

if(objinstanceofPA){

((PA)obj).runPA();

}elseif(objinstanceofPB){

((PB)obj).runPB();

}elseif(objinstanceofPC){

((PC)obj).runPC();

}elseif(objinstanceofPD){

((PD)obj).runPD();

}elseif(objinstanceofPE){

((PE)obj).runPE();

}

}

大B:“當數目變多的時候,維護ifelse是個費力氣的事情:仔細分析if,else做的工作,首先判斷類型,然後根據類型執行相應的函數。”

小A:“如何才能解決這兩個問題呢?”

大B:“首先想到的是Java的多態,多態就是根據參數執行相應的內容,能很容易的解決第二個問題,我們可以寫這樣一個類。”

publicclassvisitor{

publicvoidrun(PApa){

pa.runPA();

}

publicvoidrun(PBpb){

pb.runPB();

}

publicvoidrun(PCpc){

pc.runPC();

}

publicvoidrun(PDpd){

pd.runPD();

}

publicvoidrun(PEpe){

pe.runPE();

}

}

大B:“這樣只要調用run方法,傳入對應的參數就能執行了。”

小A:“還有一個問題就是判斷類型。”

大B:“由於重載(overloading)是靜態多分配。Java語言本身是支持‘靜態多分配’的。所以造成重載只根據傳入對象的定義類型,而不是實際的類型,所以必須在傳入前就確定類型,這可是個難的問題,因爲在容器中對象全是Object,出來後要是判斷是什麼類型必須用if(xxinstanceofxxx)這種方法。”

小A:“如果用這種方法豈不是又回到了原點,有沒有什麼更好的辦法呢?我們知道Java還有另外一個特點,覆寫(overriding),而覆寫是‘動態單分配’的,那如何利用這個來實現呢?”

大B:“看下邊這個方法:我們讓上邊的一些類PA、PB、PC、PD、PE都實現一個接口P,加入一個方法,accept()。”

publicvoidaccept(visitorv){

//把自己傳入。

v.run(this);

}

然後在visitor中加入一個方法

publicvoidrun(Pp){

//把自己傳入。

p.accept(this);

}

//這樣你在遍歷中可以這樣寫

Visitorv=newVisitor();

Iteratorie=list.iterator();

while(ie.hasNext()){

Pp=(P)ie.next();

p.accept(v);

}

}

大B:“首先執行的是‘把自己傳入2’,在這裡由於Java的特性,實際執行的是子類的accept(),也就是實際類的accept然後是‘把自己傳入1’,在這裡再次把this傳入,就明確類型,OK我們巧妙的利用overriding解決了這個問題。其實歸納一下第二部分,一個關鍵點是‘自己認識自己’,是不是很可笑。”

第14章第106章第81章第48章第124章第23章第146章第146章第113章第226章第197章第141章第87章第197章第150章第5章第108章第94章第128章第222章第103章第149章第144章第155章第167章第78章第150章第29章第55章第117章第100章第199章第227章第151章第133章第211章第227章第120章第193章第198章第124章第1章第74章第190章第90章第223章第223章第216章第178章第164章第93章第163章第185章第54章第199章第184章第222章第194章第32章第27章第157章第42章第43章第220章第203章第88章第92章第119章第56章第171章第104章第7章第49章第123章第157章第23章第47章第181章第21章第117章第196章第115章第172章第218章第91章第175章第169章第211章第116章第75章第171章第85章第27章第64章第56章第67章第177章第90章第210章第208章
第14章第106章第81章第48章第124章第23章第146章第146章第113章第226章第197章第141章第87章第197章第150章第5章第108章第94章第128章第222章第103章第149章第144章第155章第167章第78章第150章第29章第55章第117章第100章第199章第227章第151章第133章第211章第227章第120章第193章第198章第124章第1章第74章第190章第90章第223章第223章第216章第178章第164章第93章第163章第185章第54章第199章第184章第222章第194章第32章第27章第157章第42章第43章第220章第203章第88章第92章第119章第56章第171章第104章第7章第49章第123章第157章第23章第47章第181章第21章第117章第196章第115章第172章第218章第91章第175章第169章第211章第116章第75章第171章第85章第27章第64章第56章第67章第177章第90章第210章第208章
主站蜘蛛池模板: 丰台区| 浏阳市| 青州市| 红河县| 江津市| 松滋市| 来宾市| 彝良县| 资兴市| 勃利县| 东乌珠穆沁旗| 准格尔旗| 建始县| 甘肃省| 隆德县| 平遥县| 怀远县| 景谷| 辽阳市| 依兰县| 南部县| 黑龙江省| 海门市| 闵行区| 鸡东县| 平度市| 宁远县| 黑河市| 昌吉市| 永兴县| 从化市| 凤城市| 浦城县| 宜州市| 门源| 西青区| 绥阳县| 青海省| 呼和浩特市| 榆林市| 龙门县|