《PHP教程:PHP面向?qū)ο缶幊讨钊肜斫夥椒ㄖ剌d與方法覆蓋(多態(tài))》要點(diǎn):
本文介紹了PHP教程:PHP面向?qū)ο缶幊讨钊肜斫夥椒ㄖ剌d與方法覆蓋(多態(tài)),希望對(duì)您有用。如果有疑問(wèn),可以聯(lián)系我們。
什么是多態(tài)?
PHP教程
多態(tài)(Polymorphism)按字面的意思便是“多種狀態(tài)”.在面向?qū)ο笳Z(yǔ)言中,接口的多種不同的實(shí)現(xiàn)方式即為多態(tài).引用Charlie Calverts對(duì)多態(tài)的描述――多態(tài)性是允許你將父對(duì)象設(shè)置成為和一個(gè)或更多的他的子對(duì)象相等的技術(shù),賦值之后,父對(duì)象就可以根據(jù)當(dāng)前賦值給它的子對(duì)象的特性以不同的方式運(yùn)作(摘自“Delphi4編程技術(shù)內(nèi)幕”).簡(jiǎn)單的說(shuō),便是一句話:允許將子類(lèi)類(lèi)型的指針賦值給父類(lèi)類(lèi)型的指針(沒(méi)錯(cuò)這段話來(lái)自百度百科).那么多態(tài)的作用是什么,它有什么實(shí)際開(kāi)發(fā)價(jià)值呢?在實(shí)際的應(yīng)用開(kāi)發(fā)中,采用面向?qū)ο笾械亩鄳B(tài)主要在于可以將不同的子類(lèi)對(duì)象都當(dāng)作一個(gè)父類(lèi)來(lái)處理,并且可以屏蔽不同子類(lèi)對(duì)象之間所存在的差異,寫(xiě)出通用的代碼,做出通用的編程,以適應(yīng)需求的不斷變化.
PHP教程
下面便是PHP中多態(tài)的兩個(gè)實(shí)現(xiàn)?
PHP教程
辦法重載(overload)
PHP教程
重載是類(lèi)的多態(tài)的一種實(shí)現(xiàn).函數(shù)重載指一個(gè)標(biāo)識(shí)符被用作多個(gè)函數(shù)名,且能夠通過(guò)函數(shù)的參數(shù)個(gè)數(shù)或參數(shù)類(lèi)型將這些同名的函數(shù)區(qū)分開(kāi)來(lái),調(diào)用不發(fā)生混淆.即當(dāng)調(diào)用的時(shí)候,雖然辦法名字相同,但根據(jù)參數(shù)的不同可以自動(dòng)調(diào)用相應(yīng)的函數(shù).
PHP教程
class A{ public function test(){ echo "test1"; } public function test($a){ echo "test2"; } } $a=new A(); $a->test(); $a->test($a);
假如php直接支持辦法重載的話.那么上面的例子執(zhí)行后傳參和不傳參就會(huì)返回不同的值.然而php并不直接支持重載,這就意味著你如果直接按上面這樣定義的話,就會(huì)報(bào)錯(cuò)的.會(huì)報(bào)什么錯(cuò)呢?會(huì)報(bào)如下的錯(cuò)誤.
PHP教程
?PHP教程
這意思便是不能重復(fù)定義A函數(shù),報(bào)錯(cuò)的行數(shù)也正是下面這行.PHP教程
public function test($a){
所以說(shuō)php是并不直接支持重載的.合著說(shuō)了這么半天php并不支持..別急,我說(shuō)的是并不直接支持,所以說(shuō)是我們可以讓php間接支持.這時(shí)候就要用到一個(gè)函數(shù)來(lái)支持重載了.就是__call().__call()辦法必須帶有兩個(gè)參數(shù).第一個(gè)包含了被調(diào)用的辦法名稱(chēng),而第二個(gè)參數(shù)包含了傳遞給該辦法的參數(shù)數(shù)組.可以通過(guò)這個(gè)辦法實(shí)現(xiàn)類(lèi)似于函數(shù)重載的功能.看下面的代碼.
PHP教程
public function __call($method,$p) { if($method=="display"){ if(is_object($p[0])){ $this->displayObject($p[0]); }else if(is_array($p[0])){ $this->displayArray($p[0]); }else{ $this->displayScalar($p[0]); } } } //下面是對(duì)上面定義的調(diào)用 $ov=new overload; $ov->display(array(1,2,3)); $ov->display('cat');
定義辦法的時(shí)候,可以看到有三個(gè)分支,如果一個(gè)對(duì)象傳遞給display()辦法,就調(diào)用的是displayObject()辦法;如果傳遞的是一個(gè)數(shù)組,調(diào)用displayArray();傳遞的是其他的內(nèi)容的話,則調(diào)用的是displayScalar()辦法...可以看到下面調(diào)用時(shí),第一個(gè)是傳遞了一個(gè)數(shù)組,則調(diào)用displayArray().第二個(gè)傳入的不是對(duì)象也不是數(shù)組,則屬于其他內(nèi)容,調(diào)用的是displayScalar()辦法.所以這樣子就用__call()辦法實(shí)現(xiàn)了類(lèi)似于其他語(yǔ)言的辦法重載.
PHP教程
辦法覆蓋(override)
PHP教程
所謂覆蓋,從本質(zhì)上來(lái)說(shuō)就是重寫(xiě).就是當(dāng)子類(lèi)繼承父類(lèi)的一些辦法后,子類(lèi)又在其內(nèi)部定義了相同的辦法,則這個(gè)新定義的辦法會(huì)覆蓋繼承而來(lái)的父類(lèi)的辦法,子類(lèi)只能調(diào)用其內(nèi)部定義的辦法.
PHP教程
有以下幾點(diǎn)要求:
PHP教程
1.當(dāng)一個(gè)父類(lèi)和子類(lèi)有一個(gè)辦法,參數(shù)和名字完全一致,那么子類(lèi)辦法會(huì)覆蓋父類(lèi)的辦法.
PHP教程
2.在實(shí)行方法覆蓋的時(shí)候,拜訪修飾符可以是不一樣的,但是子類(lèi)的拜訪范圍必須大于等于父類(lèi)的拜訪范圍.
PHP教程
3.要求參數(shù)和名字一樣.并不是要求子類(lèi),父類(lèi)名稱(chēng)雷同.
PHP教程
下面是對(duì)這幾點(diǎn)的解釋?zhuān)?br>PHP教程
第一點(diǎn),必須參數(shù)一致,才會(huì)實(shí)現(xiàn)辦法覆蓋.當(dāng)參數(shù)個(gè)數(shù)不一致,則會(huì)報(bào)錯(cuò)(這就牽扯到上面說(shuō)所得辦法重載).當(dāng)辦法名字不一致,就不會(huì)覆蓋,只是子類(lèi)新定義的辦法.;
PHP教程
第二點(diǎn),這是php這些語(yǔ)言設(shè)計(jì)時(shí)的規(guī)定吧.我是這么理解的是拜訪高一層的東西比較容易,如果再去拜訪底層的東西權(quán)限肯定要高一些.
PHP教程
看代碼:PHP教程
class people{ protected function sing(){ echo "人唱歌"; } } class woman extends people{ public function sing(){ echo "女人唱歌"; } } $woman1=new woman(); $woman1->sing();
這樣很正常的可以輸出“女人唱歌”.但當(dāng)把woman里的sing()方法改為proctcted,父元素改成public()時(shí),即將父類(lèi)的拜訪權(quán)限設(shè)置的大于子類(lèi)后,就會(huì)報(bào)下面的錯(cuò)誤.
PHP教程
?PHP教程
?第三點(diǎn),是要求參數(shù)和名字一樣,具體便是要求參數(shù)的個(gè)數(shù)與父類(lèi)相同,而并不是參數(shù)名稱(chēng)一致.即傳遞的參數(shù)名字可以為任意,只要保證傳遞的個(gè)數(shù)相同即可.
PHP教程
以上內(nèi)容簡(jiǎn)單介紹了PHP語(yǔ)言中多態(tài)的兩個(gè)實(shí)現(xiàn).PHP教程
PS:重寫(xiě)、覆蓋、重載、多態(tài)幾個(gè)概念的區(qū)別闡發(fā)PHP教程
override->重寫(xiě)(=籠罩)、overload->重載、polymorphism -> 多態(tài)
PHP教程
override是重寫(xiě)(覆蓋)了一個(gè)辦法,以實(shí)現(xiàn)不同的功能.一般是用于子類(lèi)在繼承父類(lèi)時(shí),重寫(xiě)(重新實(shí)現(xiàn))父類(lèi)中的辦法.
重寫(xiě)(覆蓋)的規(guī)則:PHP教程
?? 1、重寫(xiě)方法的參數(shù)列表必須完全與被重寫(xiě)的方法的相同,否則不能稱(chēng)其為重寫(xiě)而是重載.
?? 2、重寫(xiě)方法的拜訪修飾符一定要大于被重寫(xiě)方法的拜訪修飾符(public>protected>default>private).
?? 3、重寫(xiě)的方法的返回值必須和被重寫(xiě)的方法的返回一致;
?? 4、重寫(xiě)的方法所拋出的異常必須和被重寫(xiě)方法的所拋出的異常一致,或者是其子類(lèi);
?? 5、被重寫(xiě)的方法不能為private,否則在其子類(lèi)中只是新定義了一個(gè)方法,并沒(méi)有對(duì)其進(jìn)行重寫(xiě).
?? 6、靜態(tài)方法不能被重寫(xiě)為非靜態(tài)的方法(會(huì)編譯出錯(cuò)).
PHP教程
overload是重載,一般是用于在一個(gè)類(lèi)內(nèi)實(shí)現(xiàn)若干重載的辦法,這些辦法的名稱(chēng)相同而參數(shù)形式不同.PHP教程
重載的規(guī)矩:PHP教程
?? 1、在使用重載時(shí)只能通過(guò)相同的方法名、不同的參數(shù)形式實(shí)現(xiàn).不同的參數(shù)類(lèi)型可以是不同的參數(shù)類(lèi)型,不同的參數(shù)個(gè)數(shù),不同的參數(shù)順序(參數(shù)類(lèi)型必須不一樣);
?? 2、不能通過(guò)拜訪權(quán)限、返回類(lèi)型、拋出的異常進(jìn)行重載;
?? 3、方法的異常類(lèi)型和數(shù)目不會(huì)對(duì)重載造成影響;
PHP教程
多態(tài)的概念比較復(fù)雜,有多種意義的多態(tài),一個(gè)有趣但不嚴(yán)謹(jǐn)?shù)恼f(shuō)法是:繼承是子類(lèi)使用父類(lèi)的辦法,而多態(tài)則是父類(lèi)使用子類(lèi)的辦法.
PHP教程
一般,我們使用多態(tài)是為了避免在父類(lèi)里大量重載引起代碼癡肥且難于維護(hù).PHP教程
舉個(gè)例子:PHP教程
public class Shape { public static void main(String[] args){ Triangle tri = new Triangle(); System.out.println("Triangle is a type of shape? " + tri.isShape());// 繼承 Shape shape = new Triangle(); System.out.println("My shape has " + shape.getSides() + " sides."); // 多態(tài) Rectangle Rec = new Rectangle(); Shape shape2 = Rec; System.out.println("My shape has " + shape2.getSides(Rec) + " sides."); //重載 } public boolean isShape(){ return true; } public int getSides(){ return 0 ; } public int getSides(Triangle tri){ //重載 return 3 ; } public int getSides(Rectangle rec){ //重載 return 4 ; } } class Triangle extends Shape { public int getSides() { //重寫(xiě),實(shí)現(xiàn)多態(tài) return 3; } } class Rectangle extends Shape { public int getSides(int i) { //重載 return i; } }
注意Triangle類(lèi)的辦法是重寫(xiě),而Rectangle類(lèi)的辦法是重載.對(duì)兩者比較,可以發(fā)現(xiàn)多態(tài)對(duì)重載的優(yōu)點(diǎn):
PHP教程
如果用重載,則在父類(lèi)里要對(duì)應(yīng)每一個(gè)子類(lèi)都重載一個(gè)取得邊數(shù)的辦法;
PHP教程
假如用多態(tài),則父類(lèi)只提供取得邊數(shù)的接口,至于取得哪個(gè)形狀的邊數(shù),怎樣取得,在子類(lèi)里各自實(shí)現(xiàn)(重寫(xiě)).PHP教程
維易PHP培訓(xùn)學(xué)院每天發(fā)布《PHP教程:PHP面向?qū)ο缶幊讨钊肜斫夥椒ㄖ剌d與方法覆蓋(多態(tài))》等實(shí)戰(zhàn)技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養(yǎng)人才。
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/8164.html