抽象類別不能直接被實例化。抽象類別只定義(或部分實作)子類別所需的方法。子類別可以繼承它並且透過實作其中的抽象方法,使抽象類別具體化。你可以用abstract關鍵字定義一個抽象類別。大多數情況下,抽象類別至少包含一個抽象方法。抽象方法用abstract關鍵字聲明,其中不能有具體內容。
abstract class ShopProductWriter{ protected $products = array(); public function addProduct(ShopProduct $shopProduct) { $this->products[] = $shopProduct; } abstract public function write();}
建立抽象方法後,要確保所有的子類別中都實作了該方法,但實作的細節可以先不確定。每個子類別都必須實作抽象類別中的所有抽象方法,或者把它們本身也聲明為抽象方法。擴展類別不僅負責簡單實作抽象類別中的方法,還必須重新聲明方法。新的實作方法的存取控制不能比抽象方法的存取控制更嚴格。新的實作方法的參數個數應該和抽象方法的參數個數一樣,重新產生對應的型別提示。
class XmlProductWriter extends ShopProductWriter{ public function write() { $str='<?xml version="1.0" encoding="UTF-8"?>'."\n"; $str.="<products>\n"; foreach ($this->products as $shopProduct) { $str.="\t<product title=\"{$shopProduct->getTitle()}\">\n"; $str.="\t\t<summary>\n"; $str.="\t\t{$shopProduct->getSummaryLine()}\n"; $str.="\t\t</summary>\n"; $str.="\t</product>\n"; } $str.="</products>\n"; print $str; } }class TextProductWriter extends ShopProductWriter{ public function write() { $str="PRODUCTS:\n"; foreach ($this->products as $shopProduct) { $str.=$shopProduct->getSummaryLine()."\n"; } print $str; } }
抽象類別提供了具體的實作的標準,而介面(interface)則是純粹的模板。介面只能定義功能,而不包含實現的內容。介面可用關鍵字interface來聲明。介面可以包含屬性和方法聲明,但是方法體為空。
interface Chargeable{ public function getPrice();}
任何實作介面的類別都要實作介面中所定義的所有方法,否則類別必須宣告為abstract。一個類別可以在聲明中使用implement關鍵字來實作某個介面。
class ShopProduct implements Chargeable { //... function getPrice() { return ($this->getPrice-$this->discount); } //...}
ShopProduct類別已經有一個getPrice()方法,那麼實作Chargeable介面還有用嗎?答案是肯定的,因為類型。實作介面的類別接受了它繼承的類別及實作的介面的類型。
任何類別都可以實作接口,介面可以有效地將不相關的型別聯結起來。一個類別可以同時繼承一個父類別和實作任意個介面。 extends子句一個在implements子句之前。
class Consultancy extends TimedService implements Bookable, Chargeable{//...}
該特性最明顯的標誌就是新關鍵字static。 static類似於self,但它指的是被呼叫的類別而不是包含類別。在本例中,它的意思是呼叫Document::create()將產生一個新的Document物件,而不是試圖實例化一個DomainObject物件。
abstract class DomainObject{ public static function create() { return new static(); } }class User extends DomainObject{ }class Document extends DomainObject{} print_r(Document::create());//输出为Document Object// (// )
static關鍵字不只可以用於實例化。和self和parent一樣,static也可以作為靜態方法呼叫的標識符,甚至是從非靜態上下文中呼叫。
abstract class DomainObject{ private $group; public function construct() { $this->group=static::getGroup(); } public static function create() { return new static(); } static function getGroup(){ return "default"; } }class User extends DomainObject{ }class Document extends DomainObject{ static function getGroup(){ return "document"; } }class SpreadSheet extends Document{} print_r(User::create()); print_r(SpreadSheet::create());//输出为User Object// (// [group:DomainObject:private]=>default // )// SpreadSheet Object// (// [group:DomainObject:private]=>document// )
以上是深入了解PHP物件導向、模式與實務-高階特性(二)的詳細內容。更多資訊請關注PHP中文網其他相關文章!