抽象類是指在 class 前加了 abstract 關鍵字且存在抽象方法(在類方法 function 關鍵字前加了 abstract 關鍵字)的類。php
抽象類不能被直接實例化。抽象類中只定義(或部分實現)子類須要的方法。子類能夠經過繼承抽象類並經過實現抽象類中的全部抽象方法,使抽象類具體化。編程
若是子類須要實例化,前提是它實現了抽象類中的全部抽象方法。若是子類沒有所有實現抽象類中的全部抽象方法,那麼該子類也是一個抽象類,必須在 class 前面加上 abstract 關鍵字,而且不能被實例化。
引用連接函數
接口(Interface)—— 定義行爲this
抽象類(Abstract Class) —— 實現行爲.net
具體類(class)——執行行爲
引用連接設計
抽象類就是一個類的服務提供商,擁有衆多服務,你不用必須用,當須要的時候你來用就能夠,若是你以爲不提供服務不滿意,你還能夠本身來作。code
抽象方法是必須實現的方法。就象動物都要呼吸。可是魚用鰓呼吸,豬用肺呼吸。
動物類要有呼吸方法。怎麼呼吸就是子類的事了。對象
引用連接blog
按照我目前的知識理解:繼承
保持程序的一致性
抽象類限制了實現的方法,也是爲了保持一致性
增長代碼重用性,例如一些公共類不須要實現,只須要調用裏面的方法就能夠了。
如今有不少討論和建議提倡用interface代替abstract類,二者從理論上能夠作通常性的混用,可是在實際應用中,他們仍是有必定區別的。抽象類通常做爲公共的父類爲子類的擴展提供基礎,這裏的擴展包括了屬性上和行爲上的。而接口通常來講不考慮屬性,只考慮方法,使得子類能夠自由的填補或者擴展接口所定義的方法,就像JAVA王子所說的事件中的適配器就是一個很好的應用。
用一個簡單的例子,好比說一個教師,咱們把它做爲一個抽象類,有本身的屬性,好比說年齡,教育程度,教師編號等等,而教師也是分不少種類的,咱們就能夠繼承教師類而擴展特有的種類屬性,而廣泛屬性已經直接繼承了下來。
而接口呢~仍是拿教師作例子,教師的行爲不少,除了和普通人相同的之外,還有職業相關的行爲,好比改考卷,講課等等,咱們把這些行爲定義成無body的方 法,做爲一個集合,它是一個interface。而教師張三李四的各自行爲特色又有不一樣,那麼他們就能夠擴展本身的行爲body。從這點意義上來講,interface偏重於行爲。
<?php abstract class Shape{ //這是一個抽象類,不能實例化 protected $color; //抽象類裏面通常都是使用protected來保護屬性,這是封裝的意義 public function __construct($color = 'red') { //抽象類可使用構造方法,主要是爲了方便代碼重用,構造方法裏面也可使用默認參數,當沒有配置參數的時候,就會使用默認的參數,寫法如上 $this->color = $color; } public function getColor() { //只是爲了演示須要的一個方法 return $this->color; } abstract public function getArea(); //構造方法是爲了限制代碼,對於繼承這個構造類的子類,必須限制擁有這個構造方法,主要爲了保持代碼一致性。 } class Square extends Shape{ protected $length = 4; public function getArea() { return pow($this->$length, 2); } } class Circle extends Shape{ //這裏由於沒有構造方法getArea,因此代碼容許會報錯的。 } $shape = new Square(); var_dump($shape); ?>
抽象類不能被直接實例化,抽象類中只定義子類須要的方法,子類能夠繼承而且經過實現其中的抽象方法,使抽象類具體化。例如一個名爲media的類,他是用於描述各類公開出版的共同性質,由於media不表示真實的實體,而是一些類似實體的泛化表示,因此不實例化,這樣就須要聲明爲抽象類,而後再由各類的派生的Media類繼承此抽象類
抽象類的每一個子類都必須實現抽象類中的全部抽象方法,或者把他們自身也聲明爲抽象方法。
擴展類不只僅負責簡單實現抽象類的方法,還必須從新聲明方法,新的方法不能比抽象方法的訪問控制更嚴格,新的實現方法的參數個數應該和抽象方法的參數個數同樣。
接口定義了實現某種服務的通常規範,聲明瞭必須的函數和常量,可是不指定如何實現。關鍵是要創建必須實現的一組通常原則,只有知足了這些原則才能說實現了這個接口。
抽象類提供了具體實現的標準,而接口則是純粹的模板。接口只能定義功能而不包含實現的內容。
任何實現接口的類都要實現接口中所定義的全部方法,不然類必須聲明爲abstract。
實現接口的類接受他的繼承的類以及實現的接口的類型。
若是要建立一個模型,這個模型將由一些緊密相關的對象引用,就能夠採用抽象類,若是要建立將由一些不想關的對象採用的功能,應該用接口。
若是必須從多個來源繼承行爲,就是用接口。
若是知道全部類都會共享一個公共的行爲實現,就使用抽象類,並在其中實現行爲。接口沒法實現。
一個類只能extends一個父類,但能夠貫徹多個接口。
接口類就是一個類的領導者,指明方向,子類必須完成它指定方法。
當有不少人一塊兒開發一個項目時,可能都會去調用別人寫的一些類,那你就會問,我怎麼知道他的某個功能的實現方法是怎麼命名的呢,這個時候php接口類就起到做用了,當咱們定義了一個接口類時,它裏面的方式是下面的子類必須實現的,好比
interface Shop { public function buy($gid); public function sell($gid); public function view($gid); }
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 . '的商品'; } }
有時候,咱們須要設計一個物品,好比shape,這個shape有不一樣的形狀,有不一樣的顏色,可做不一樣的運動,等等。固然咱們能夠把這些都放在一個類裏面,但這樣,如前面說的,只是過程編程,不是OO編程。你會說,像上面例子同樣,作一個抽象類,而後在子類裏實現全部的功能。好象不錯,進步了。這樣子類裏面要實現形狀,顏色,運動等功能,OK嗎?記住,OO裏面還有一條原則,爲了最大程度的作到代碼重用,一個類裏最好只實現一個功能,也就是說,一個類作形狀,一個類作顏色,一個類作運動 。這樣若是其餘的類要用到顏色的功能時,咱們就能夠重用這個顏色類,同理,這樣咱們能夠很容易的重用運動類,形狀類,等等。
但這樣問題出來了,如今咱們要用到上面全部的功能,但又分散在三個類裏面,怎麼辦?這時咱們就要用到抽象類和接口了。選定一個跟shape關聯最大的一項–形狀,把它作成抽象類, 其餘兩樣,把它們作成接口,而後在子類裏面extends一個抽象類,再implements兩個接口就好了。如:
class Square extends Shape implements 顏色, 運動, ... { ... }
抽象類就是一個類的服務提供商,擁有衆多服務,你不用必須用,當須要的時候你來用就能夠,若是你以爲不提供服務不滿意,你還能夠本身來作。
這裏是一個例子,想上面同樣我定義了一個商店類,抽所了它全部像的部分,買(buy),賣(sell),看(view),而且抽象類裏都實現了這些方法,那麼繼承它的子類就自動得到了這些方法,子類就作它本身獨特的東西,減小代碼的重複,提升複用性。
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); } }
在抽象類裏面設置抽象方法
在oo設計時,會把一些通用的方法放在一個類裏,但考慮到子類繼承時的差別性,又不能把它事先實現,就只好用到這個抽象類或接口了。這裏很清楚的顯示了在抽象類裏,咱們貫徹了設原用到點setCenter()的方法,這樣,當子類繼承它時,就不用再重複寫這個設原點的方法了。那麼爲何draw的方法要設定成抽象方法呢?這是由於不一樣的子類要用不一樣的實現方法。
abstract class Shape { function setCenter($x, $y) { $this->x = $x; $this->y = $y; } abstract function draw(); protected $x, $y; }
參考:http://chengxudaren.com/index.php?act=article&op=detail&a_id=152