淺談PHP面向物件程式設計(七)
7.0 抽象類與介面
當定義一個類時,常常需要定義一些方法來描述該類的行為特徵、但有時這些方法的實現方式是無法確定的,此時就可以使用抽象類和介面。
抽象類和介面用於提高程式的靈活性、抽象類是一種特殊的類,而介面又是一種待殊的抽象類。
接下來本節將針對抽象類和介面進行詳細講解。
7.1 抽象類
當在定義一個類的 時候,其中所霜的某些方法暫時並不能完全定義出來,而是讓其繼承的類來實現,此時就可以用到抽象類。
比如定又一個動物類,每種動物有一“叫” 的方法,面每種動物叫的方式不同,因此可以將動物類定義為一個抽象類。
定義抽象類需要使用 abstract
1 abstract class 類名{ 2 3 //類成員 4 5 }
由於每種動物叫的方式不同,所以需要將動物同的shut方法定義成抽象的, 即只有方法宣告面設有方法體的方法,在子類繼承時再來編寫該方法的具體實規,這種特珠的方法稱為抽象方法,其語法格式如下
1 abstract function 方法名 ();
為了更好的理解抽象類和抽象方法的使用,接下來t通過個案例來演示
例7-19
1 <?php 2 //使用abstract關鍵字宣告一個抽象類 3 abstractclass Animal{ 4 //在抽象類中宣告抽象方法 5 abstract public function shout(); 6 } 7 //定義Dog類繼承自Animal類 8 class Dog extends Animal{ 9 //實現抽象方法shout() 10 public function shout() 11 { 12 echo "汪汪......<br>"; 13 } 14 } 15 //定義Cat類繼承自Animal類 16 class Cat extends Animal{ 17 //實現抽象方法shout() 18 public function shout() 19 { 20 echo "喵喵......<br>"; 21 } 22 } 23 $dog=new Dog(); 24 $dog->shout(); 25 $cat=new Cat(); 26 $cat->shout(); 27 ?>
執行結果
例7-19中,第3-6行程式碼定義了一個抽象類Animal. 然後使Dog類和Cat類繼承Animal類並實現抽象方法shout(). 最後分別呼叫cat物件和dog物件的shout()方法,輸出不同動物對應的叫聲
注意:
(1)抽象類不能被例項化。
(2)抽象類可以沒有抽象方法,但有抽象方法的抽象關才有意義,一旦類包含了抽象方法,則這個類必須宣告為abstract。
(3)抽象關中可以有非抽象方法、成員屬性和常量。
(4)抽象方法不能有函式體,它只能存在於抽象類中。
(5)如果一個類繼承了某個抽象類,則它必須實現該抽象類的所有抽象方法、除非它自己也宣告為抽象類。
7.2 介面
如果一個抽象類中的所有方法都是抽象的、則可以將這個類用另外一種方式來定義。即介面。在定義介面時,需要使用interface關鍵字,具體示例程式碼如下:
1 interface Animal{ 2 3 public function run (); 4 5 public function breathe(); 6 7 }
定義介面與定義一個標準的類類似,但其中定義的所有的方法都是空的。
需要注意的是介面中的所有方法都是公有的,也不能使用 final關鍵字來修飾
由於介面中定義的都是抽象方法,沒有具體實現,需要通過類來實現介面。實現介面使用 implements 關鍵字。
接下來通過一個案例來學習,如例7-20 所示
1 <?php 2 //定義Animal介面 3 interface Animal{ 4 public function run(); 5 public function shout(); 6 } 7 //定義Dog類,實現了Animal介面 8 class Dog implements Animal{ 9 public function run(){ 10 echo "狗在奔跑<br>"; 11 } 12 public function shout(){ 13 echo "汪汪……<br>"; 14 } 15 } 16 //定義Cat類,實現了Animal介面 17 class Cat implements Animal{ 18 public function run(){ 19 echo "貓在奔跑<br>"; 20 } 21 public function shout(){ 22 echo "喵喵……<br>"; 23 } 24 } 25 $cat=new Cat(); 26 $cat->run(); 27 $cat->shout(); 28 $dog=new Dog(); 29 $dog->run(); 30 $dog->shout(); 31 ?>
執行結果
在例7-20中,首先定義了介面Animal,在介面Animal中聲明瞭抽象方法run()和shout(). 然後分別通過Cat類和Dog類實現了Animal介面最後通過cat和dog物件呼叫run()和shout()方法。在PHP中類是單繼承的,但一個類卻可以實現多個介面,並且這些介面之間用逗號分展開,接下來通過一個具體的案例來學習, 如例7-21所示。
例7-21
1 <?php 2 //定義Animal介面 3 interface Animal{ 4 public function run(); 5 public function shout(); 6 } 7 //定義LandAnimal介面 8 interface LandAnimal{ 9 public function LiveOnLand(); 10 } 11 //定義Dog類,實現了Animal和LandAnimal介面 12 class Dog implements Animal,LandAnimal{ 13 public function LiveOnLand(){ 14 echo"狗在陸地上生活<br>"; 15 } 16 public function run(){ 17 echo "狗在奔跑<br>"; 18 } 19 public function shout(){ 20 echo "汪汪……<br>"; 21 } 22 } 23 $dog=new Dog(); 24 $dog->LiveOnLand(); 25 $dog->run(); 26 $dog->shout(); 27 ?>
執行結果
在例7-21中,動物類Dog同時實現了介面Animal和LandAnimal,
通過dog物件呼叫了LandAnimal中的LiveOnLand()方法
和Animal介面中的run()和shout()方法
擴充套件-繼承和介面的配合使用
在使用implements關鍵宇實現介面的同 時,還可以使用extends 關鍵字繼承一個類。
即在繼承一個類的同時實現介面,但一定要先使用extends繼承一個類,再使用implements實現介面,
具體示例如下所示:
1 class 類名 extends 父類名 implements 介面1,介面2,....介面n{ 2 3 //實現所有介面中的抽象方法 4 5 }
PHP的單繼承機制可保證類的純潔性,比C++中的多繼承機制簡潔。
但是不可否認,對子類功能的擴充套件有一定影響。
所以我們認為實現介面可以看作是對繼承的一種補充。
實現介面可在不打破繼承關係的前提下,對某個類功能擴充套件,非常靈活。