PHP abstract與interface之間的區別

luyaran發表於2017-01-06
1、抽象類需要繼承,用extends,而介面需要實現,用implements;
2、一個類可以實現多個介面,但只能繼承一個抽象類
3、介面中每個方法都只有宣告而沒有實現,其中的每個方法實現類必須要實現;而抽象類中只需要實現抽象方法,其它方法可以選擇性的實現;

4、介面中只能宣告public的方法,不能宣告private和protected的方法,不能對方法進行實現,也不能宣告例項變數;但是抽象類中可以

1.php 介面類:interface

其實他們的作用很簡單,當有很多人一起開發一個專案時,可能都會去呼叫別人寫的一些類,那你就會問,我怎麼知道他的某個功能的實現方法是怎麼命名的呢,這個時候php介面類就起到作用了,當我們定義了一個介面類時,它裡面的方式是下面的子類必須實現的,比如 :

複製程式碼 程式碼如下:

 interface Shop
 {
       public function buy($gid);
       public function sell($gid);
       public function view($gid);
 }

我宣告一個shop介面類,定義了三個方法:買(buy),賣(sell),看(view),那麼繼承此類的所有子類都必須實現這3個方法少一個都 不行,如果子類沒有實現這些話,就無法執行。實際上介面類說白了,就是一個類的模板,一個類的規定,如果你屬於這類,你就必須遵循我的規定,少一個都不 行,但是具體你怎麼去做,我不管,那是你的事,如:
複製程式碼 程式碼如下:

class BaseShop implements Shop
{
public function buy($gid)
{
echo('你購買了ID為 :'.$gid.'的商品');
}
public function sell($gid)
{
echo('你賣了ID為 :'.$gid.'的商品');
}
public function view($gid)
{
echo('你檢視了ID為 :'.$gid.'的商品');
}
}

你想想,在一個多人合作的大專案裡面,有了介面類是多麼的方便,這樣你就不用去問別人,你的某某功能的方法名是什麼了,當然如果你們喜歡這樣我也沒有辦法。

結論 : 介面類就是一個類的領導者,指明方向,子類必須完成它指定方法。

2.php 抽象類 : abstract

其實抽象類和介面類有一部分很像,記得在哪裡看見這樣一句話,抽象類就把類像的部分抽出來,這句看上去很搞笑,其實它說出了抽象類的真理,抽象類的 作用是,當你發現你的很多類裡面用很多方法你不斷的在重複寫,那你就可以考慮使用抽象類了,你可能會說“我不是可以重寫一個類每個公共類我個例項化一個這 個公共類,呼叫相同的方法就可以了”,這裡是可以,實際上抽象類做的工作也就是這個,不過他省去了你例項化的這個步驟,讓你就像直接呼叫本類方法一樣方 便,而且你還可以過載這個方法。如:

複製程式碼 程式碼如下:

  abstract class BaseShop
  {
      public function buy($gid)
      {
          echo('你購買了ID為 :'.$gid.'的商品');
      }
      public function sell($gid)
      {
          echo('你賣了ID為 :'.$gid.'的商品');
     }
     public function view($gid)
     {
         echo('你檢視了ID為 :'.$gid.'的商品');
     }
 }
 class BallShop extends BaseShop
 {
     var $itme_id = null;
     public function __construct()
     {
         $this->itme_id = 2314;
     }
     public function open()
     {
         $this->sell($this->itme_id);
     }
 }


這裡是一個例子,想上面一樣我定義了一個商店類,抽出了它所有像的部分,買(buy),賣(sell),看(view),並且抽象類裡都實現了這些方法,那麼繼承它的子類就自動獲得了這些方法,子類就做它自己獨特的東西,介紹程式碼的重複,提高複用性。

結論: 抽象類就是一個類的服務提供商,擁有眾多服務,你不用必須用,當需要的時候你來用就可以,如果你覺得不提供服務不滿意,你還可以自己來做。而abstract function 方法和interface有些相似,就是父類中生宣告的方法,子類中必須實現,但是沒有用abstract宣告的方法將成為子類的公共方法,沒有必要在子類中必須實現

一、 抽象類abstractclass

1 .抽象類是指在 class 前加了 abstract 關鍵字且存在抽象方法(在類方法 function 關鍵字前加了 abstract 關鍵字)的類。

2 .抽象類不能被直接例項化。抽象類中只定義(或部分實現)子類需要的方法。子類可以通過繼承抽象類並通過實現抽象類中的所有抽象方法,使抽象類具體化。

3 .如果子類需要例項化,前提是它實現了抽象類中的所有抽象方法。如果子類沒有全部實現抽象類中的所有抽象方法,那麼該子類也是一個抽象類,必須在 class 前面加上 abstract 關鍵字,並且不能被例項化。

 

[c-sharp] viewplaincopyprint?
  1. abstract class A  
  2. {  
  3.       
  4.     protected $value1 = 0;  
  5.     private $value2 = 1;  
  6.     public $value3 = 2;  
  7.       
  8.     public function my_print()  
  9.     {  
  10.         echo "hello,world/n";  
  11.     }  
  12.       
  13.     abstract protected function abstract_func1();  
  14.     abstract protected function abstract_func2();  
  15. }  
  16. abstract class B extends A  
  17. {  
  18.     public function abstract_func1()  
  19.     {  
  20.        echo "implement the abstract_func1 in class A/n";  
  21.     }  
  22.       
  23.     //abstract protected function abstract_func2();  
  24. }  
  25. class C extends B  
  26. {  
  27.     public function abstract_func2()  
  28.     {  
  29.        echo "implement the abstract_func2 in class A/n";  
  30.     }  
  31. }  

4 .如果像下面這樣建立了一個繼承自 A 的子類 B ,但是不實現抽象方法 abstract_func() 

 

  1. Class B extends A{};  

那麼程式將出現以下錯誤:

 

  1. Fatal error: Class B contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (A::abstract_func)  

5 .如果 B 實現了抽象方法 abstract_func() ,那麼 B  abstract_func() 方法的訪問控制不能比 A  abstract_func() 的訪問控制更嚴格,也就是說:

(1)      如果 A  abstract_func() 宣告為 public ,那麼 B  abstract_func() 的宣告只能是 public ,不能是 protected  private

(2)      如果 A  abstract_func() 宣告為 protected ,那麼 B  abstract_func() 的宣告可以是 public  protected ,但不能是 private

(3)      如果 A  abstract_func() 宣告為 private ,嘿嘿,不能定義為 private 哦!( Fatalerror :Abstract function A::abstract_func() cannot be declaredprivate 

二、 介面interface

1 .抽象類提供了具體實現的標準,而介面則是純粹的模版。介面只定義功能,而不包含實現的內容。介面用關鍵字 interface 來宣告。

2  interface 是完全抽象的,只能宣告方法,而且只能宣告 public 的方法,不能宣告 private  protected 的方法,不能定義方法體,也不能宣告例項變數 。然而, interface 卻可以宣告常量變數 。但將常量變數放在 interface 中違背了其作為介面的作用而存在的宗旨,也混淆了 interface 與類的不同價值。如果的確需要,可以將其放在相應的 abstractclass  Class 中。

 

  1. interface iA  
  2. {  
  3.     const AVAR=3;  
  4.     public function iAfunc1();  
  5.     public function iAfunc2();  
  6. }  
  7. echo iA:: AVAR;  

 

3 .任何實現介面的類都要實現介面中所定義的所有方法

 

  1. class E implements iA  
  2. {  
  3.     public function iAfunc1(){echo "in iAfunc1";}  
  4.     public function iAfunc2(){echo "in iAfunc2";}  
  5. }  

否則該類必須宣告為 abstract 

 

  1. abstract class E implements iA{}  

4 .一個類可以在宣告中使用 implements 關鍵字來實現某個介面。這麼做之後,實現介面的具體過程和繼承一個僅包含抽象方法的抽象類是一樣的。一個類可以同時繼承一個父類和實現任意多個介面。 extends 子句應該在 implements 子句之前。 PHP 只支援繼承自一個父類,因此 extends 關鍵字後只能跟一個類名。

 

  1. interface iB  
  2. {  
  3.     public function iBfunc1();  
  4.     public function iBfunc2();  
  5. }  
  6. class D extends A implements iA,iB  
  7. {  
  8.     public function abstract_func1()  
  9.     {  
  10.        echo "implement the abstract_func1 in class A/n";  
  11.     }  
  12.     public function abstract_func2()  
  13.     {  
  14.        echo "implement the abstract_func2 in class A/n";  
  15.     }  
  16.     public function iAfunc1(){echo "in iAfunc1";}  
  17.     public function iAfunc2(){echo "in iAfunc2";}  
  18.     public function iBfunc1(){echo "in iBfunc1";}  
  19.     public function iBfunc2(){echo "in iBfunc2";}  
  20. }  
  21.    
  22. class D extends B implements iA,iB  
  23. {  
  24.     public function abstract_func1()  
  25.     {  
  26.        parent::abstract_func1();  
  27.        echo "override the abstract_func1 in class A/n";  
  28.     }  
  29.     public function abstract_func2()  
  30.     {  
  31.        echo "implement the abstract_func2 in class A/n";  
  32.     }  
  33.     public function iAfunc1(){echo "in iAfunc1";}  
  34.     public function iAfunc2(){echo "in iAfunc2";}  
  35.     public function iBfunc1(){echo "in iBfunc1";}  
  36.     public function iBfunc2(){echo "in iBfunc2";}  
  37. }  

5 .介面不可以實現另一個介面,但可以繼承多個

 

  1. interface iC extends iA,iB{}  
  2. class F implements iC  
  3. {  
  4.     public function iAfunc1(){echo "in iAfunc1";}  
  5.     public function iAfunc2(){echo "in iAfunc2";}  
  6.     public function iBfunc1(){echo "in iBfunc1";}  
  7.     public function iBfunc2(){echo "in iBfunc2";}  
  8. }  

三、 抽象類和介面的異同

1. 相同點:

(1)      兩者都是抽象類,都不能例項化。

(2)      interface 實現類及 abstractclass 的子類都必須要實現已經宣告的抽象方法。

2. 不同點:

(1)      interface 需要實現,要用 implements ,而 abstractclass 需要繼承,要用 extends 

(2)      一個類可以實現多個 interface ,但一個類只能繼承一個 abstractclass 

(3)      interface 強調特定功能的實現,而 abstractclass 強調所屬關係。

(4)      儘管 interface 實現類及 abstractclass 的子類都必須要實現相應的抽象方法,但實現的形式不同。 interface 中的每一個方法都是抽象方法,都只是宣告的 (declaration, 沒有方法體 ) ,實現類必須要實現。而 abstractclass 的子類可以有選擇地實現。這個選擇有兩點含義: a)abstract class 中並非所有的方法都是抽象的,只有那些冠有 abstract 的方法才是抽象的,子類必須實現。那些沒有 abstract 的方法,在 abstractclass 中必須定義方法體; b) abstract class 的子類在繼承它時,對非抽象方法既可以直接繼承,也可以覆蓋;而對抽象方法,可以選擇實現,也可以留給其子類來實現,但此類必須也宣告為抽象類。既是抽象類,當然也不能例項化。

(5)      abstractclass  interface  class 的中介。 abstract class  interface  class 中起到了承上啟下的作用。一方面, abstractclass 是抽象的,可以宣告抽象方法,以規範子類必須實現的功能;另一方面,它又可以定義預設的方法體,供子類直接使用或覆蓋。另外,它還可以定義自己的例項變數,以供子類通過繼承來使用。

(6)      介面中的抽象方法前不用也不能加 abstract 關鍵字,預設隱式就是抽象方法,也不能加 final 關鍵字來防止抽象方法的繼承。而抽象類中抽象方法前則必須加上 abstract 表示顯示宣告為抽象方法。

(7)      介面中的抽象方法預設是 public 的,也只能是 public 的,不能用 private  protected 修飾符修飾。而抽象類中的抽象方法則可以用 public protected 來修飾,但不能用 private 

3.interface 的應用場合

(1)      類與類之間需要特定的介面進行協調,而不在乎其如何實現。

(2)      作為能夠實現特定功能的標識存在,也可以是什麼介面方法都沒有的純粹標識。

(3)      需要將一組類視為單一的類,而呼叫者只通過介面來與這組類發生聯絡。

(4)      需要實現特定的多項功能,而這些功能之間可能完全沒有任何聯絡。

4. abstractclass 的應用場合

一句話,在既需要統一的介面,又需要例項變數或預設的方法的情況下,就可以使用它。最常見的有:

(1)      定義了一組介面,但又不想強迫每個實現類都必須實現所有的介面。可以用 abstractclass 定義一組方法體,甚至可以是空方法體,然後由子類選擇自己所感興趣的方法來覆蓋。

(2)      某些場合下,只靠純粹的介面不能滿足類與類之間的協調,還必需類中表示狀態的變數來區別不同的關係。 abstract 的中介作用可以很好地滿足這一點。

(3)      規範了一組相互協調的方法,其中一些方法是共同的,與狀態無關的,可以共享的,無需子類分別實現;而另一些方法卻需要各個子類根據自己特定的狀態來實現特 定的功能 


相關文章