標籤:http 使用 io strong 2014 ar 問題 cti
抽象類別與介面相似,都是一種比較特殊的類。抽象類別是一種特殊的類,而介面也是一種特殊的抽象類別。它們通常配合物件導向的多態性一起使用。雖然聲明和使用都比較容易,但它們的作用在理解上會困難一點。
①抽象類別
在OOP語言中,一個類可以有一個或多個子類,而每個類都有至少一個公有方法作為外部代碼訪問它的介面。而抽象方法就是為了方便繼承而引入的。本節中先來介紹一下抽象類別和抽象方法的聲明,然後再說明其用途。在聲明抽象類別之前,我們先瞭解一下什麼是抽象方法。抽象方法就是沒有方法體的方法,所謂沒有方法體是指在方法聲明時沒有花括弧及其中的內容,而是在聲明方法時直接在方法名後加上分號結束。另外在聲明抽象方法時,還要使用關鍵字abstract來修飾。聲明抽象方法的格式如下所示:
abstract function fun1(); //不能有花括弧,就更不能有方法體中的內容了
abstract function fun2(); //直接在方法名的括弧後面加上分號結束,還要使用abstract修飾
只要在聲明類時有一個方法時抽象方法,那麼這個類就是抽象類別,抽象類別也要使用abstract關鍵字來修飾。在抽象類別中可以有不是抽象的成員方法和成員屬性,但存取權限不能使用private關鍵字修飾為私人的。下面的例子在Person類中聲明了兩個抽象方法say()和eat(),則Person類就是一個抽象類別,需要使用abstract標識。代碼如下所示:
| 123456789101112131415161718 |
<?php abstract class Person{ protected $name; protected $country; function __construct($name="",$country="china"){ $this ->name = $name; $this ->country = $country; } abstract function say(); abstract function eat(); function run(){ echo "使用兩條腿走路<br>"; } }?> |
在上例中聲明了一個抽象類別Person,在這個類中定義了兩個成員屬性、一個構造方法和兩個抽象方法,還有一個是非抽象的方法。抽象類別就像是一個“半成品”的類,在抽象類別中有沒有被實現的抽象方法,所以抽象類別是不能被執行個體化的,即建立不了對象,也就不能直接使用它。既然抽象類別是一個“半成品”的類,那麼使用抽象類別有什麼作用呢?使用抽象類別就包含了繼承關係,它是為它的子類定義公用介面,將它的操作(可能是部分,也可能是全部)交給子類去實現。就是將抽象類別作為子類重載的模板使用,定義抽象類別就相當於定義了一種規範,這種規範要求子類去遵守。當子類繼承抽象類別以後,就必須把抽象類別中的抽象方法按照子類自己的需要去實現。子類必須把父類中的抽象方法全部都實現,否則子類中還存在抽象方法,所以還是抽象類別,也不能執行個體化對象。在下例中聲明了兩個類,分別實現上例中聲明的抽象類別Person。代碼如下所示:
| 1234567891011121314151617181920212223242526272829303132 |
<?php class ChineseMan extends Person{ function say(){ echo $this ->name."是".$this->country."人,講漢語<br>"; } function eat(){ echo $this ->name."使用筷子吃飯<br>"; } } class Americans extends Person{ function say(){ echo $this ->name."是".$this->country."人,講英語<br>"; } function eat(){ echo $this ->name."使用刀子和叉子吃飯<br>"; } } $chianeseMan = new ChineseMan("高洛峰","中國"); $americans = new Americans ("alex","美國"); $chineseMan ->say(); $chineseMan ->eat(); $americans ->say(); $americans ->eat();?> |
在上例中聲明了兩個類去繼承抽象類別Person,並將Person類中的抽象方法按各自的需求分別實現,這樣兩個子類就都可以建立對象了。抽象類別Person就可以看成是一個模板,類中的抽象方法自己不去實現,只是規範了子類中必須要有父類中聲明的抽象方法,而且要按照自己的特點實現抽象方法的內容。
②介面技術
因為PHP只支援單繼承,也就是說每個類只能繼承一個父類。當聲明的新類繼承抽象類別實現模板以後,它就不能再有其他父類了。為瞭解決這個問題,PHP引入了介面。介面是一種特殊的抽象類別,而抽象類別又是一種特殊的類。如果抽象類別中的所有方法都是抽象方法,我們就可以換另外一種聲明方式,使用“介面”技術。介面中聲明的方法必須都是抽象方法,另外不能再介面中聲明變數,只能使用const關鍵字聲明為常量的成員屬性,而且介面中所有成員都必須有public的存取權限。類的聲明是使用“class”關鍵字標識的,而介面的聲明則是使用“interface”關鍵字標識的。聲明介面的格式如下所示:
| 123456 |
<?phpinterface 介面名稱{ //使用interface關鍵字聲明介面常量成員 //介面中的成員屬性只能是常量,不能是變數抽象方法 //介面中的所有方法必須是抽象方法,不能有非抽象的方法存在}?> |
介面中的所有方法都要求是抽象方法,所以就不需要在方法前使用abstract關鍵字標識了。而且在介面中也不需要顯式地使用public存取權限進行修飾,因為預設許可權就是public的,也只能是公有的。另外介面和抽象類別一樣也不能執行個體化對象,它是一種更嚴格的規範,也需要通過子類來實現。但可以直接使用介面名稱在介面外面去擷取常量成員的值。一個介面的聲明例子,代碼如下所示:
| 1234567 |
<?phpinterface one{const CONSTANT = ‘CONSTANT value‘;function fun1();function fun2();}?> |
也可以使用extends關鍵字讓一個介面去繼承另一個介面,實現介面之間的擴充。在下面的例子中聲明一個Two介面繼承了上例中的One介面。代碼如下所示:
| 123456 |
<?phpinterface Two extends one{function fun3();function fun4();}?> |
如果需要使用介面中的成員,則需要通過子類去實現介面中的全部抽象方法,然後建立子類的對象去調用在子類中實現後的方法。但通過類去繼承介面時需要使用implements關鍵字來實現,而並不是使用extends關鍵字完成。如果需要使用抽象類別去實現介面中的部分方法,也需要使用implements關鍵字實現。在下面的例子中聲明一個抽象類別Three去實現One介面中的部分方法,但要想執行個體化對象,這個抽象類別還需要有子類把它所有的抽象方法都實現才行。聲明一個Four類去實現One介面中全部方法。代碼如下所示:
| 1234567891011121314151617181920212223242526 |
<?phpinterface one{const CONSTANT = ‘CONSTANT value‘;function fun1();function fun2();} //聲明一個抽象類別去實現介面One中的第二個方法abstract class Three implements One{ //只實現介面中的一個抽象方法function fun2(){//具體的實現內容由子類自己決定}} //聲明一個類實現介面One中的全部抽象方法class Four implements One{function fun1(){//具體的實現內容由子類自己決定} function fun2(){//具體的實現內容由子類自己決定}} ?> |
PHP是單繼承的,一個類只能有一個父類,但是一個類可以實現多個介面。將要實現的多個介面之間使用逗號分隔開,而且在子類中藥將所有介面中的抽象方法全部實現才可以建立對象。就相當於一個類要遵守多個規範,就像我們不僅要遵守國家的法律,如果是在學校,還需要遵守學校的校規一樣。實現多個介面的格式如下所示:
class 類名 implements 介面一,介面二,……介面n{
實現所有介面中的抽象方法
}
實現多個介面是使用“implements”關鍵字,同時還可以使用“extends”關鍵字繼承一個類。即在繼承類的同時實現多個介面,但一定更要先使用extends繼承一個類,再去使用inplements實現多個介面。使用格式如下所示:
class 類名 extends 父類名 implements 介面一,介面二,……介面n{
實現所有介面中的抽象方法
}
除了上述的一些應用外,還有很多地方可以使用使用介面,例如對於一些已經開發好的系統,在結構上進行較大的調整已經不太現實,這時可以通過自訂一些介面並追加相應的實現來完成功能結構的擴充。
>> 本文固定連結: http://php.ncong.com/php_course/oop/abstract.html
>> 轉載請註明: 恩聰php 2014年07月25日 於 恩聰PHP學習教程 發表