抽象類別是使用abstract關鍵字聲明的類。要將類中某個方法聲明為抽象方法,只需要省略掉包含所有大括弧的方法實現體,將方法聲明的程式碼用分號結束即可。
簡單地說,當我們在建立一個基礎對象的時候,其中所需的某些方法暫時並沒有完整地定義出來,我們就可以用到抽象類別。而後將方法中的細節延遲到繼承者來實現。
比如定義一個 動物類,動物有 吃東西 這一方法,而每種動物吃東西的方式又不同,比如牛吃草,老虎吃肉。因此我們就可以將動物類定義為一個抽象類別。
當然抽象類別中也可以包括完整實現的方法,而不單單只有抽象方法,另外抽象類別不能被執行個體化。
abstract class Food { public $name; abstract protected function getCount();}abstract class Animal { abstract function eat(Food $food);}
繼承抽象類別的時候用關鍵字extends,PHP只支援單一繼承,原因在於,當兩個或更多的類定義了相同的方法時,多重繼承會導致不必要的複雜性。在實現抽象方法的時候,不能高於聲明抽象方法時的存取層級(private > protected > public)。
class Grass extends Food { public $name = 'grass'; // 由於基類Food中此方法聲明時為protected,所在這裡不能用private修飾(可以用protected, public) public function getCount() { }}class Meat extends Food { public $name = 'meat'; public function getCount() { }}class Cow extends Animal { public $name = 'cow'; function eat(Food $food) { echo $this->name; if (!($food instanceof Grass)) { echo ' don\'t '; } echo ' eat ', $food->name, '.<br/>'; }}$cow = new Cow();$grass = new Grass();$meat = new Meat();// cow eat grass.$cow->eat($grass);// cow don't eat meat.$cow->eat($meat);
介面是一種類似類的結構,通常用來聲明API,而不關心如何?這個API。介面中只能聲明抽象方法。
interface IPerson { function marry($person);}
實現介面用關鍵字implements,一個類要實現一個介面,必須實現介面中的所有方法。一個類可以實現多個介面,多個介面之間用逗號隔開。
class Person implements IPerson { protected $sex, $name, $age; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } public function marry($person) { if ($person instanceof Person) { echo 'You can marry.'; } else { echo 'Oh no, you can\'t marry.'; } }}// 當然下面還可以繼續擴充class Boy extends Person { public $sex = 'male';}class Girl extends Person { public $sex = 'female';}$boy = new Boy('cctv', 22);$girl = new Girl('asdf', 21);$boy->marry($girl);