最近開始學習PHP+MySQL,記錄下學習過程中的重點內容吧,然後考慮把開發網站的過程也寫一個系列Blog。
這篇blog主要介紹了Abstract Class和Interface的區別。
和C++中的抽象類概念一樣,包含有純虛函數(Java和Php中叫abstract method)的類叫做Abstract Class。 我們有時候也把abstract Class叫做base class,因為base class不能直接生成對象。
我們來看代碼:
abstract class abc { public function xyz() { return 1; } } $a = new abc();//this will throw error in php
PHP中的abstract class和其他oop語言一樣,我們用關鍵字 abstract 來聲明一個抽象類,如果你想直接生成這個類的對象,會報錯。
abstract class testParent { public function abc() { //body of your funciton } } class testChild extends testParent { public function xyz() { //body of your function } } $a = new testChild();
testChild通過關鍵字extends 繼承了抽象類 testParent, 然後我們就可以生成 一個testChild的對象了。
類似於C++中的純虛函數,我們只能在抽象類中申明Abstract method,而只能而且必須在子類中定義它。
其實這種說法不是絕對的,但是為了方便記憶,大多說的教材這樣說,來我們回顧一下Effective C++中的關於pure virtual函數的講解。
“Pure Virtual函數必須在derived class中重新聲明,但是它們也可以有自己的實現”
class Airplane{ public: virtual void fly(const Airport& destination) = 0; .... }; void Airplane::fly(const Airport& destination){ // 缺省行為,將飛機飛到指定的目的地 }
class ModelA: public Airplane{ public: virtual void fly(const Airport& destination) {Airplane::fly(destination);} .... }; class ModelB: public Airplane{ public: virtual void fly(const Airport& destination); .... }; void ModelB:: fly(const Airport& destination){ // 將C型飛機飛到指定的地方 }實際上,我們在derived class ModelA中對virtual method做了一個inline調用。
想在的fly被分割為兩個基本要素:
其聲明部分表現的是接口(這個derived class必須使用的)
其定義部分則變現出缺省行為(那是derived class可能使用的,但只有在它們明確提出申請時才是)
以上內容摘自《Effective C++改善程序與設計的55個具體做法 》條款34: 區分接口繼承和實現繼承
讓我們回來繼續討論PHP中的abstract method的實現。
abstract class abc { abstract protected function f1($a , $b); } class xyz extends abc { protected function f1($name , $address) { echo $name , $address; } } $a = new xyz();
一旦你在abstract class中聲明了一個abstract method,那麼所有繼承這個class的subclass都必須要去declare這個method,否則,php會報錯。
abstract class parentTest { abstract protected function f1(); abstract public function f2(); //abstract private function f3(); //this will trhow error } class childTest { public function f1() { //body of your function } public function f2() { //body of your function } protected function f3() { //body of your function } } $a = new childTest();
注意到在abstract class中 f1函數是protected,但是在subclass中我們可以將其聲明為public的。no any visibility is less restricted than public.
Interface in oop enforce definition of some set of method in the class。
interface將會強迫用戶去實現一些method。例如有一個class中必須要求set ID和Name這兩個屬性,那麼我們就可以把這個class申明為interface,這樣所有繼承自這個class的derived class都將強制必須實現setId和setName兩個操作
Interface abc { public function xyz($b); }
在這個interface裡面我們聲明了一個method xyz,則任何時候,subclass中都必須申明這樣的一個method xyz
class test implements abc { public function xyz($b) { //your function body } }
在interface中,只能使用public,而不能使用諸如protected和private
interface template1 { public function f1(); } interface template2 extends template1 { public function f2(); } class abc implements template2 { public function f1() { //Your function body } public function f2() { //your function body } }你可以用extends關鍵字來繼承interface,好像class那樣。
這裡的template2將包含所有template1的屬性,因此在implements自template2的class abc,將必須實現 function f1和f2,
你還可以extends multiple interface:
interface template1 { public function f1(); } interface template2 { public function f2(); } interface template3 extends template1, template2 { public function f3(); } class test implements template3 { public function f1() { //your function body } public function f2() { //your function body } public function f3() { //your function body } }
同時,你的class也可以implements多個interface
interface template1 { public function f1(); } interface template2 { public function f2(); } class test implments template1, template2 { public function f1() { //your function body } public function f2() { //your function body } }
繼承自interface中的method必須有同樣的參數規范,例如下面的代碼是可行的:
interface template1 { public function f1($a) } class test implements template1 { public function f1($a) { echo $a; } }
interface template1 { public function f1($a) } class test implements template1 { public function f1() { echo $a; } }
interface template1 { public function f1($a) } class test implements template1 { public function f1($name) { echo $name; } }
interface template1 { public function f1($a = 20) } class test implements template1 { public function f1($name = ankur) { echo $name; } }
1. In abstract classes this is not necessary that every method should be abstract. But in interface every method is abstract.
在Abstract class中並非所有的method都必須是抽象的,但是在interface中所有的method都自動成為抽象的。就是在子類中必須聲明和實現
2. Multiple and multilevel both type of inheritance is possible in interface. But single and multilevel inheritance is possible in abstract classes.
multiple和multilevel inheritance,我不知道改怎麼翻譯更好,multiple inheritance意思是 在interface中,一個class可以同時implements好多個interface;但是在abstract classes中,只能extends一個class。
當然你extends的這個class可能又extentds別的class,這就是所謂的multilevel inheritance。
3. Method of php interface must be public only. Method in abstract class in php could be public or protected both.
interface中的method必須是public的,但是在abstract class中可以是public或者protected。
4. In abstract class you can define as well as declare methods. But in interface you can only defined your methods.
在abstract class中你可以同時聲明(declare)和定義(define)methodes,但是在interface中你只能定義那個methods