- 相關(guān)推薦
PHP面向?qū)ο缶幊讨钊肜斫夥椒?/p>
文章主要介紹了PHP面向?qū)ο缶幊讨钊肜斫夥椒ㄖ剌d與方法覆蓋(多態(tài))的相關(guān)資料,需要的朋友可以參考下
什么是多態(tài)?
多態(tài)(Polymorphism)按字面的意思就是“多種狀態(tài)”。在面向?qū)ο笳Z言中,接口的多種不同的實(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)單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針(沒錯(cuò)這段話來自百度百科)。那么多態(tài)的作用是什么,它有什么實(shí)際開發(fā)價(jià)值呢?在實(shí)際的應(yīng)用開發(fā)中,采用面向?qū)ο笾械亩鄳B(tài)主要在于可以將不同的子類對(duì)象都當(dāng)作一個(gè)父類來處理,并且可以屏蔽不同子類對(duì)象之間所存在的差異,寫出通用的代碼,做出通用的編程,以適應(yīng)需求的不斷變化。
下面就是PHP中多態(tài)的兩個(gè)實(shí)現(xiàn)
方法重載(overload)
重載是類的多態(tài)的一種實(shí)現(xiàn)。函數(shù)重載指一個(gè)標(biāo)識(shí)符被用作多個(gè)函數(shù)名,且能夠通過函數(shù)的參數(shù)個(gè)數(shù)或參數(shù)類型將這些同名的函數(shù)區(qū)分開來,調(diào)用不發(fā)生混淆。即當(dāng)調(diào)用的時(shí)候,雖然方法名字相同,但根據(jù)參數(shù)的不同可以自動(dòng)調(diào)用相應(yīng)的函數(shù)。
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ò)誤。
這意思就是不能重復(fù)定義A函數(shù),報(bào)錯(cuò)的行數(shù)也正是下面這行。
public function test($a){
所以說php是并不直接支持重載的。合著說了這么半天php并不支持。。別急,我說的是并不直接支持,所以說是我們可以讓php間接支持。這時(shí)候就要用到一個(gè)函數(shù)來支持重載了。就是__call()。__call()方法必須帶有兩個(gè)參數(shù)。第一個(gè)包含了被調(diào)用的方法名稱,而第二個(gè)參數(shù)包含了傳遞給該方法的參數(shù)數(shù)組。可以通過這個(gè)方法實(shí)現(xiàn)類似于函數(shù)重載的功能?聪旅娴拇a。
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)了類似于其他語言的方法重載。
方法覆蓋(override)
所謂覆蓋,從本質(zhì)上來說就是重寫。就是當(dāng)子類繼承父類的一些方法后,子類又在其內(nèi)部定義了相同的方法,則這個(gè)新定義的方法會(huì)覆蓋繼承而來的父類的方法,子類只能調(diào)用其內(nèi)部定義的方法。
有以下幾點(diǎn)要求:
1.當(dāng)一個(gè)父類和子類有一個(gè)方法,參數(shù)和名字完全一致,那么子類方法會(huì)覆蓋父類的方法。
2.在實(shí)行方法覆蓋的時(shí)候,訪問修飾符可以是不一樣的,但是子類的訪問范圍必須大于等于父類的訪問范圍。
3.要求參數(shù)和名字一樣。并不是要求子類,父類名稱相同。
下面是對(duì)這幾點(diǎn)的解釋:
第一點(diǎn),必須參數(shù)一致,才會(huì)實(shí)現(xiàn)方法覆蓋。當(dāng)參數(shù)個(gè)數(shù)不一致,則會(huì)報(bào)錯(cuò)(這就牽扯到上面說所得方法重載)。當(dāng)方法名字不一致,就不會(huì)覆蓋,只是子類新定義的方法。;
第二點(diǎn),這是php這些語言設(shè)計(jì)時(shí)的規(guī)定吧。我是這么理解的是訪問高一層的東西比較容易,如果再去訪問底層的東西權(quán)限肯定要高一些。
看代碼:
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í),即將父類的訪問權(quán)限設(shè)置的大于子類后,就會(huì)報(bào)下面的錯(cuò)誤。
第三點(diǎn),是要求參數(shù)和名字一樣,具體就是要求參數(shù)的個(gè)數(shù)與父類相同,而并不是參數(shù)名稱一致。即傳遞的參數(shù)名字可以為任意,只要保證傳遞的個(gè)數(shù)相同即可。
以上內(nèi)容簡(jiǎn)單介紹了PHP語言中多態(tài)的兩個(gè)實(shí)現(xiàn)。
PS:重寫、覆蓋、重載、多態(tài)幾個(gè)概念的區(qū)別分析
override->重寫(=覆蓋)、overload->重載、polymorphism -> 多態(tài)
override是重寫(覆蓋)了一個(gè)方法,以實(shí)現(xiàn)不同的功能。一般是用于子類在繼承父類時(shí),重寫(重新實(shí)現(xiàn))父類中的方法。
重寫(覆蓋)的規(guī)則:
1、重寫方法的參數(shù)列表必須完全與被重寫的方法的相同,否則不能稱其為重寫而是重載.
2、重寫方法的訪問修飾符一定要大于被重寫方法的訪問修飾符(public>protected>default>private)。
3、重寫的方法的返回值必須和被重寫的方法的返回一致;
4、重寫的方法所拋出的異常必須和被重寫方法的所拋出的異常一致,或者是其子類;
5、被重寫的方法不能為private,否則在其子類中只是新定義了一個(gè)方法,并沒有對(duì)其進(jìn)行重寫。
6、靜態(tài)方法不能被重寫為非靜態(tài)的方法(會(huì)編譯出錯(cuò))。
overload是重載,一般是用于在一個(gè)類內(nèi)實(shí)現(xiàn)若干重載的方法,這些方法的名稱相同而參數(shù)形式不同。
重載的規(guī)則:
1、在使用重載時(shí)只能通過相同的方法名、不同的參數(shù)形式實(shí)現(xiàn)。不同的參數(shù)類型可以是不同的參數(shù)類型,不同的參數(shù)個(gè)數(shù),不同的參數(shù)順序(參數(shù)類型必須不一樣);
2、不能通過訪問權(quán)限、返回類型、拋出的異常進(jìn)行重載;
3、方法的異常類型和數(shù)目不會(huì)對(duì)重載造成影響;
多態(tài)的概念比較復(fù)雜,有多種意義的多態(tài),一個(gè)有趣但不嚴(yán)謹(jǐn)?shù)恼f法是:繼承是子類使用父類的方法,而多態(tài)則是父類使用子類的方法。
一般,我們使用多態(tài)是為了避免在父類里大量重載引起代碼臃腫且難于維護(hù)。
舉個(gè)例子:
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() { //重寫,實(shí)現(xiàn)多態(tài)
return 3;
}
}
class Rectangle extends Shape
{
public int getSides(int i) { //重載
return i;
}
}
【PHP面向?qū)ο缶幊讨钊肜斫夥椒ā肯嚓P(guān)文章:
PHP面向?qū)ο蟮倪M(jìn)階學(xué)習(xí)09-06
PHP語言面向?qū)ο蟮膬?nèi)容06-22
php面向?qū)ο蟮某绦蛟O(shè)計(jì)10-12
PHP面向?qū)ο笕筇攸c(diǎn)學(xué)習(xí)06-14
深入理解PHP的.htaccess文件08-11