本節講解的內容
前言
在PHP中的物件導向是通過定義類,來完成對象的樣本化,而PHP的抽象類別和介面類可以說是類的一種規範,通過定義這兩種類來對類進行強制限制式,雖然這兩種都是對類的約束,但本質上他們還是有區別的。
抽象類別
抽象類別的概念我們可以用動物的繼承關係來說明問題,當我們寫父類Animal類時,其中有兩個方法sleep(),eat(),因為不知道具體是什麼動物而無法確定方法中寫什麼內容。這是我們就可以用抽象類別進行實現。
<?php//通過關鍵字abstract來聲明抽象類別abstract class Animal{ protected $name; protected $age; //聲明該方法是抽象方法 abstract public function sleep(); abstract public function eat();}
當父類的一些方法不能確定的時候,可以用abstract關鍵字來修飾該方法,稱為抽象方法,而用abstract修飾的類稱為抽象類別。
基本文法:
abstract class 類名{ abstract 存取修飾詞 函數名(參數列表);}
在開發中當我們想讓繼承該類的所有子類都重寫該類的方法,就可以用抽象方法來實現。抽象類別就好比某個東西的架子也可以說是一個模板,有了模板就可以可以根據模板實現具體的功能。,而模板和具體事物的這種關係是通過繼承類傳遞的。就好比一台電腦,通過模板來製作一台台電腦。而抽象類別定義出來就是需要被繼承的。
<?phpabstract class Animal{ protected $name; protected $age; abstract public function sleep(); abstract public function eat();}class Dog extends Animal{}......結果........Fatal error: Class Dog contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Animal::sleep, Animal::eat) in D:\mywamp\Apache24\htdocs\zendstudio\yunsuanfu\chouxiang.php on line 13
當一個類繼承了抽象類別後,在子類中就需要實現父類的所有抽象方法上面報的錯誤就是說在父類中包含2個抽象方法,子類必須實現該抽象方法。而關於抽象類別的特點可以總結如下:
抽象類別是不能被樣本化的,不能通過抽象類別來new一個對象,會報一個Cannot instantiate abstract class錯誤。
抽象類別中可以沒有抽象方法的,在抽象類別中都是普通方法,但是類名是用abstract修飾的。
<?phpabstract class Animal{ protected $name; protected $age; public function sleep(){ } public function eat(){ }}
抽象類別可以有普通的成員方法,屬性等
<?phpabstract class Animal{ protected $name; protected $age; abstract public function sleep(); abstract public function eat(); public function cry(){ }}
如果一個類中有抽象方法,那麼這個類必須是抽象類別。
抽象方法是沒有方法體的
abstract public function eat();
沒有{},也就是說沒有方法體。
一個類繼承了抽象類別,則子類必須實現抽象類別的所有抽象方法,或者子類自己也聲明為抽象類別
介面
介面的初衷和抽象類別是一樣的,不知道方法裡面怎麼實現的時候可以用介面來實現。而介面的定義是:給出一些沒有實現的方法,封裝到一起,到某個類要使用的時候,再根據具體情況把這些方法寫出來,介面的出現體現了高內聚低耦合的特點。
<?phpinterface iTechnical{ public function fly();}
基本文法:
interface 介面名{ //方法, 在介面中,所有的方法都不能有方法體, 即都是抽象方法}
介面類和抽象類別大致一樣,那介面具體是什麼呢?上面有說到抽象類別就好比一台筆記本的架子、模板,然後根據模板建立具體的筆記本,而沒有筆記本都有幾個usb介面,而介面類就好比這些筆記本上的介面,是一個擴充的實現。就像動物一樣都繼承了動物特有的特性吃,睡等,但是突然一隻動物在別的地方實現了寫字的本領,這種本領就是通過介面進行擴充的。
介面的命名一般是在類名的第一個字母是小寫i開頭。在介面類中所有的方法都預設是抽象方法。所以並不需要寫abstract來聲明。
介面的實現
我們定義一個介面當然是讓別的類去實現的,這裡說的是實現,而不是繼承,介面和別的類之間是實現的關係,也就是類實現了某一介面,用implements關鍵字實現。
interface iTechnical{ public function fly();}class Dog implements iTechnical{ public function fly(){ echo '<br>飛'; }}
當然在子類中必須實現介面中所有的方法。
關於介面的特點有以下幾點:
介面類和抽象類別一樣是不能被執行個體化的。
介面中所有的方法都不能有主體,因為都是抽象方法。
一個類可以實現多個介面,逗號隔開(繼承只能是一個)
class Dog implements 介面1,介面2{}
介面中可以有屬性,但只能是常量 ,預設是public, 但不能用public 顯式修飾
介面中的方法都必須是public的,介面就是用來繼承的所以用public,如果沒有寫修飾符,預設是public
一個介面不能繼承其它的類,但是可以繼承別的介面
抽象和介面的區別
在PHP中繼承是單繼承的,也就是一個類最多隻能有一個父類,這種單繼承的機制可以保證類的純潔性。但是這種機制對子類功能擴充有一定的影響。
介面的出現可以說是對繼承的一種補充,繼承是層級的,不太靈活,而介面卻沒有它比抽象要靈活的多。並且實現介面在不打破繼承關係的前提下,對子類的功能進行擴充。
它們兩個的關係圖可以理解為這樣:
final的使用
在上面的介紹中每個類都是可以被繼承的,如果我們有一個類,我們不想讓子類去重寫裡面的某個方法,或者不想讓別的類去繼承該類,就可以用到關鍵字final。final中文意思:最後的,最終的,可以用來修飾類或者方法。
final可以修飾方法或者類,如果修飾方法,則表示該方法不可以被繼承類去重寫,如果final 修飾了一個類,則表示該類不可以被繼承。
基本文法:
final class 類名{}class 類名{ final 存取修飾詞 function 函數名(形參){}}
修飾類和修飾方法。
<?php final class A{ } class B extends A{ } .....結果..... Class B may not inherit from final class (A)
不能繼承用final修飾的類。
<?php class A{ final public function sum($num1,$num2){ return $num1 + $num2; } } class B extends A{ public function sum($num1,$num2){ return $num1 + $num2; } } .....結果..... Cannot override final method A::sum()
從結果中可以看出來不能重寫用final定義的方法。
在使用final時,只能用來修飾類或者方法,不能修飾屬性。當一個類被final修飾後,類中的方法就不需要被final修飾,因為類都不能繼承了,方法就不能重寫。同時final修飾的類是可以被執行個體化的。
如果一個方法被final修飾,是可以被繼承的,但是不能被重寫。
<?php class A{ final public function sum($num1,$num2){ return $num1 + $num2; } } class B extends A{ } $b = new B(); echo $b -> sum(1,2); .......結果....... 3
在我們寫單例模式時,說過當時的單例模式是不完善的,可以通過繼承來得到不同的對象,在這裡我們使用final關鍵字修飾單例類,防止繼承,這樣就不能通過繼承的到別的對象。
類常量
類常量和普通的常量是一個概念,當不希望一個成員變數被修改,希望該變數的值是固定不變的。這時可以用const去修飾該成員變數,這樣這個變數就自動成為常量。在類中的常量稱為類常量。前面我們講過定義常量有兩種方式define()和關鍵字const,在類中必須使用const這種方式,使用define()是會報錯的。
<?php class A{ const PI = 3.1415926; public function getPI(){ return A::PI; } } $a = new A(); echo $a -> getPI(); echo '<br>'; echo A::PI; ......結果...... 3.1415926 3.1415926
類常量的命名一般是全部用大寫字母,中間用底線隔開,同時常量前面沒有$符號。常量必須在定義的時候就賦值。同時常量的前面不能有修飾符,預設是public。
常量的訪問形式
常量的訪問形式分為兩種,一種是在類的內部進行訪問,一種是在類的外部進行訪問。
內部訪問
通過 類名::常量名進行訪問。
class A{ const PI = 3.1415926; public function getPI(){ return A::PI;//通過類名進行訪問 }}
通過 self::常量名進行訪問
class A{ const PI = 3.1415926; public function getPI(){ return self::PI;//通過類名進行訪問 }}
可以通過self進行訪問說明常量是屬於類的,並不屬於對象的。
外部存取
通過類名::常量名訪問。
echo A::PI;
通過對象名::常量名訪問
$a = new A();echo $a::PI;
不過推薦使用第一種,通過類名進行訪問。
如果一個類中有常量,則在繼承的時候常量也是可以被繼承的。同時常量的資料類型不能是對象。
總結
PHP中抽象和介面應用讓我們的更加清楚的把握需求的骨架,更好的搭建我們的代碼體系。同時利用抽象和介面降低代碼的耦合度。利於代碼的擴充。
以上就是PHP基礎教程十二之抽象、介面的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!