欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP面向?qū)ο缶幊讨钊肜斫夥椒ㄖ剌d與方法覆蓋(多態(tài))

 更新時(shí)間:2015年12月24日 09:59:31   作者:這算什么艾迪  
這篇文章主要介紹了PHP面向?qū)ο缶幊讨钊肜斫夥椒ㄖ剌d與方法覆蓋(多態(tài))的相關(guān)資料,需要的朋友可以參考下

什么是多態(tài)?

多態(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ō),就是一句話:允許將子類類型的指針賦值給父類類型的指針(沒(méi)錯(cuò)這段話來(lái)自百度百科)。那么多態(tài)的作用是什么,它有什么實(shí)際開(kāi)發(fā)價(jià)值呢?在實(shí)際的應(yīng)用開(kāi)發(fā)中,采用面向?qū)ο笾械亩鄳B(tài)主要在于可以將不同的子類對(duì)象都當(dāng)作一個(gè)父類來(lái)處理,并且可以屏蔽不同子類對(duì)象之間所存在的差異,寫(xiě)出通用的代碼,做出通用的編程,以適應(yīng)需求的不斷變化。

下面就是PHP中多態(tài)的兩個(gè)實(shí)現(xiàn) 

方法重載(overload)

重載是類的多態(tài)的一種實(shí)現(xiàn)。函數(shù)重載指一個(gè)標(biāo)識(shí)符被用作多個(gè)函數(shù)名,且能夠通過(guò)函數(shù)的參數(shù)個(gè)數(shù)或參數(shù)類型將這些同名的函數(shù)區(qū)分開(kāi)來(lái),調(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){ 

所以說(shuō)php是并不直接支持重載的。合著說(shuō)了這么半天php并不支持。。別急,我說(shuō)的是并不直接支持,所以說(shuō)是我們可以讓php間接支持。這時(shí)候就要用到一個(gè)函數(shù)來(lái)支持重載了。就是__call()。__call()方法必須帶有兩個(gè)參數(shù)。第一個(gè)包含了被調(diào)用的方法名稱,而第二個(gè)參數(shù)包含了傳遞給該方法的參數(shù)數(shù)組??梢酝ㄟ^(guò)這個(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)了類似于其他語(yǔ)言的方法重載。

方法覆蓋(override)

所謂覆蓋,從本質(zhì)上來(lái)說(shuō)就是重寫(xiě)。就是當(dāng)子類繼承父類的一些方法后,子類又在其內(nèi)部定義了相同的方法,則這個(gè)新定義的方法會(huì)覆蓋繼承而來(lái)的父類的方法,子類只能調(diào)用其內(nèi)部定義的方法。

有以下幾點(diǎn)要求:

1.當(dāng)一個(gè)父類和子類有一個(gè)方法,參數(shù)和名字完全一致,那么子類方法會(huì)覆蓋父類的方法。

2.在實(shí)行方法覆蓋的時(shí)候,訪問(wèn)修飾符可以是不一樣的,但是子類的訪問(wèn)范圍必須大于等于父類的訪問(wèn)范圍。

3.要求參數(shù)和名字一樣。并不是要求子類,父類名稱相同。

下面是對(duì)這幾點(diǎn)的解釋:

第一點(diǎn),必須參數(shù)一致,才會(huì)實(shí)現(xiàn)方法覆蓋。當(dāng)參數(shù)個(gè)數(shù)不一致,則會(huì)報(bào)錯(cuò)(這就牽扯到上面說(shuō)所得方法重載)。當(dāng)方法名字不一致,就不會(huì)覆蓋,只是子類新定義的方法。;

第二點(diǎn),這是php這些語(yǔ)言設(shè)計(jì)時(shí)的規(guī)定吧。我是這么理解的是訪問(wèn)高一層的東西比較容易,如果再去訪問(wèn)底層的東西權(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í),即將父類的訪問(wèn)權(quán)限設(shè)置的大于子類后,就會(huì)報(bào)下面的錯(cuò)誤。

 

 第三點(diǎn),是要求參數(shù)和名字一樣,具體就是要求參數(shù)的個(gè)數(shù)與父類相同,而并不是參數(shù)名稱一致。即傳遞的參數(shù)名字可以為任意,只要保證傳遞的個(gè)數(shù)相同即可。

以上內(nèi)容簡(jiǎn)單介紹了PHP語(yǔ)言中多態(tài)的兩個(gè)實(shí)現(xiàn)。

PS:重寫(xiě)、覆蓋、重載、多態(tài)幾個(gè)概念的區(qū)別分析

override->重寫(xiě)(=覆蓋)、overload->重載、polymorphism -> 多態(tài)

override是重寫(xiě)(覆蓋)了一個(gè)方法,以實(shí)現(xiàn)不同的功能。一般是用于子類在繼承父類時(shí),重寫(xiě)(重新實(shí)現(xiàn))父類中的方法。
重寫(xiě)(覆蓋)的規(guī)則:

   1、重寫(xiě)方法的參數(shù)列表必須完全與被重寫(xiě)的方法的相同,否則不能稱其為重寫(xiě)而是重載.
   2、重寫(xiě)方法的訪問(wèn)修飾符一定要大于被重寫(xiě)方法的訪問(wèn)修飾符(public>protected>default>private)。
   3、重寫(xiě)的方法的返回值必須和被重寫(xiě)的方法的返回一致;
   4、重寫(xiě)的方法所拋出的異常必須和被重寫(xiě)方法的所拋出的異常一致,或者是其子類;
   5、被重寫(xiě)的方法不能為private,否則在其子類中只是新定義了一個(gè)方法,并沒(méi)有對(duì)其進(jìn)行重寫(xiě)。
   6、靜態(tài)方法不能被重寫(xiě)為非靜態(tài)的方法(會(huì)編譯出錯(cuò))。

overload是重載,一般是用于在一個(gè)類內(nèi)實(shí)現(xiàn)若干重載的方法,這些方法的名稱相同而參數(shù)形式不同。

重載的規(guī)則:

   1、在使用重載時(shí)只能通過(guò)相同的方法名、不同的參數(shù)形式實(shí)現(xiàn)。不同的參數(shù)類型可以是不同的參數(shù)類型,不同的參數(shù)個(gè)數(shù),不同的參數(shù)順序(參數(shù)類型必須不一樣);
   2、不能通過(guò)訪問(wèn)權(quán)限、返回類型、拋出的異常進(jìn)行重載;
   3、方法的異常類型和數(shù)目不會(huì)對(duì)重載造成影響;

多態(tài)的概念比較復(fù)雜,有多種意義的多態(tài),一個(gè)有趣但不嚴(yán)謹(jǐn)?shù)恼f(shuō)法是:繼承是子類使用父類的方法,而多態(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() { //重寫(xiě),實(shí)現(xiàn)多態(tài)
   return 3;
  }
}
class Rectangle extends Shape 
{
  public int getSides(int i) { //重載
  return i;
  }
}

注意Triangle類的方法是重寫(xiě),而Rectangle類的方法是重載。對(duì)兩者比較,可以發(fā)現(xiàn)多態(tài)對(duì)重載的優(yōu)點(diǎn):

如果用重載,則在父類里要對(duì)應(yīng)每一個(gè)子類都重載一個(gè)取得邊數(shù)的方法;

如果用多態(tài),則父類只提供取得邊數(shù)的接口,至于取得哪個(gè)形狀的邊數(shù),怎樣取得,在子類里各自實(shí)現(xiàn)(重寫(xiě))。

相關(guān)文章

  • php生成唯一uid的解決方法詳解

    php生成唯一uid的解決方法詳解

    在用戶系統(tǒng)中,生成唯一uid,是很多初級(jí)程序員頭痛的事情,因?yàn)槟悴⒉荒鼙WC完全的唯一性,如果要保證唯一性,必須要查一次數(shù)據(jù)庫(kù)。本文將介紹php生成唯一uid的思路,希望能對(duì)大家有所幫助
    2021-11-11
  • Laravel中Facade的加載過(guò)程與原理詳解

    Laravel中Facade的加載過(guò)程與原理詳解

    Facade其實(shí)是一個(gè)容器中類的靜態(tài)代理,他可以讓你以靜態(tài)的方式來(lái)調(diào)用存放在容器中任何對(duì)象的任何方法,下面這篇文章主要給大家介紹了關(guān)于Laravel中Facade的加載過(guò)程與原理的相關(guān)資料,需要的朋友可以參考下。
    2017-09-09
  • thinkPHP實(shí)現(xiàn)簽到功能的方法

    thinkPHP實(shí)現(xiàn)簽到功能的方法

    這篇文章主要介紹了thinkPHP實(shí)現(xiàn)簽到功能的方法,實(shí)例分析了mysql數(shù)據(jù)表的構(gòu)造及thinkPHP簽到功能的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-03-03
  • Smarty模板語(yǔ)法詳解

    Smarty模板語(yǔ)法詳解

    這篇文章主要介紹了Smarty模板語(yǔ)法,結(jié)合實(shí)例形式詳細(xì)分析了Smarty模板的注釋、變量、引號(hào)、函數(shù)等基本語(yǔ)法與使用技巧,需要的朋友可以參考下
    2019-07-07
  • thinkPHP中分頁(yè)用法實(shí)例分析

    thinkPHP中分頁(yè)用法實(shí)例分析

    這篇文章主要介紹了thinkPHP中分頁(yè)用法,結(jié)合實(shí)例形式詳細(xì)分析了thinkPHP數(shù)據(jù)查詢及使用分頁(yè)類實(shí)現(xiàn)分頁(yè)效果的相關(guān)技巧,需要的朋友可以參考下
    2015-12-12
  • Yii2漢字轉(zhuǎn)拼音類的實(shí)例代碼

    Yii2漢字轉(zhuǎn)拼音類的實(shí)例代碼

    這篇文章主要介紹了Yii2漢字轉(zhuǎn)拼音類的實(shí)例代碼,需要的朋友可以參考下
    2017-04-04
  • php遍歷目錄與文件夾的多種方法詳解

    php遍歷目錄與文件夾的多種方法詳解

    介紹幾個(gè)php遍歷目錄的方法,可以遍歷目錄及目錄中的文件,供大家參考
    2013-11-11
  • php mysql 封裝類實(shí)例代碼

    php mysql 封裝類實(shí)例代碼

    這篇文章主要介紹了php mysql 封裝類實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • PHP內(nèi)核學(xué)習(xí)教程之php opcode內(nèi)核實(shí)現(xiàn)

    PHP內(nèi)核學(xué)習(xí)教程之php opcode內(nèi)核實(shí)現(xiàn)

    opcode是計(jì)算機(jī)指令中的一部分,用于指定要執(zhí)行的操作, 指令的格式和規(guī)范由處理器的指令規(guī)范指定,通過(guò)本文給大家介紹PHP內(nèi)核學(xué)習(xí)教程之php opcode內(nèi)核實(shí)現(xiàn),感興趣的朋友一起學(xué)習(xí)吧
    2016-01-01
  • php文件擴(kuò)展名判斷及獲取文件擴(kuò)展名的N種方法

    php文件擴(kuò)展名判斷及獲取文件擴(kuò)展名的N種方法

    本篇文章主要通過(guò)代碼給大家介紹php文件擴(kuò)展名判斷以及獲取文件擴(kuò)展名的N種方法,需要的朋友跟著腳本之家小編一起學(xué)習(xí)學(xué)習(xí)吧
    2015-09-09

最新評(píng)論