PHP強(qiáng)化之18 - 抽象類與接口

[toc]

一、abstract

1肛走、抽象類
在實際開發(fā)中辙芍,我們可以有這樣一種類,是其它類的父類羹与,但是他本身并不需要去實例化故硅,主要用途是用于讓子類來繼承,這樣可以達(dá)到代碼的復(fù)用纵搁,同時利于項目設(shè)計者去設(shè)計類吃衅。

  • 定義抽象類:
abstract class 類名{
  //屬性
  //方法
}
  • 繼承抽象類
class 類名 extends 抽象類
{
 
}

2、抽象方法

抽象方法不能有方法體腾誉。所謂沒有方法體就是在方法聲明的時候沒有大括號以及其中的內(nèi)容徘层,而是直接聲明時在方法名后加上分號結(jié)束。

  • 如:
abstract function 方法名();

3利职、注意

1)如果一個類使用了abstract來修飾趣效,則該類就是抽象類(不能被實例化)。
2)抽象類可以沒有抽象方法猪贪,同時還可以有實現(xiàn)了的方法跷敬。
3)一個類只要有abstract方法,則該類必須聲明為abstract類热押。
4)抽象方法是作為子類方法重載的模板使用的西傀,如果一個A類繼承了一個抽象B類,則要求A類實現(xiàn)B類的所有抽象方法(除非A類也是抽象類)桶癣。
5)如果子類沒有全部實現(xiàn)抽象類中的所有抽象方法拥褂,那么該子類也是一個抽象類,必須在 class 前面加上 abstract 關(guān)鍵字牙寞,并且不能被實例化饺鹃。
6)抽象方法不能為private。

二、interface

1悔详、簡介

接口就是給出一些沒有實現(xiàn)的方法镊屎,封裝到一起,到某個類要使用的時候伟端,再根據(jù)具體情況把這些方法寫出來杯道。

接口是更加抽象的抽象類匪煌,抽象類可以存在有方法體的方法责蝠,而接口里的所有方法都沒有方法體。

接口體現(xiàn)了程序設(shè)計的多態(tài)和高內(nèi)聚低偶合的設(shè)計思想萎庭。

2霜医、定義接口類

interface A
{
    public function a();
    Public function b();
}

3、實現(xiàn)接口類

class X implements A
{
    public function a(){
    }
    public function a(){
    }
}

4驳规、注意

1)不能去實例化一個接口肴敛。
2)接口中的所有方法都不能有方法體。
3)一個接口可以繼承多個其它接口吗购。
4)一個類可以實現(xiàn)多個接口(用逗號隔開)医男。
5)接口中可以有屬性,但必須是常量捻勉,默認(rèn)是public镀梭。
6)接口的方法必須都是public,默認(rèn)public踱启。(但將常量變量放在接口中違背了其作為接口的作用而存在的宗旨报账,也混淆了interface與類的不同價值。所以不建議)
7)一個類可以同時繼承又實現(xiàn)某些接口埠偿。(extends子句應(yīng)該在implements子句之前)
8)任何實現(xiàn)接口的類都要實現(xiàn)接口中所定義的所有方法透罢。

三、Abstract Class與Interface的異同

1冠蒋、 相同點:

1)兩者都是抽象類羽圃,都不能實例化。
2)interface 實現(xiàn)類及 abstract class 的子類都必須要實現(xiàn)已經(jīng)聲明的抽象方法抖剿。

2统屈、不同點:

1)interface需要實現(xiàn),要用 implements 牙躺;而 abstract class 需要繼承愁憔,要用 extends 。
2)一個類可以實現(xiàn)多個 interface 孽拷,但一個類只能繼承一個abstract class吨掌。
3) interface 中的每一個方法都是抽象方法,實現(xiàn)類必須要實現(xiàn);而 abstract class 的子類可以有選擇地實現(xiàn)膜宋。
4)接口中的抽象方法前不用也不能加 abstract 關(guān)鍵字窿侈,默認(rèn)隱式就是抽象方法,也不能加 final 關(guān)鍵字來防止抽象方法的繼承秋茫;而抽象類中抽象方法前則必須加上 abstract 表示顯示聲明為抽象方法史简。
5)接口中的抽象方法默認(rèn)是 public 的,也只能是 public 的肛著;而抽象類中的抽象方法則可以用 public 或 protected 來修飾圆兵,但不能用 private 。

四枢贿、Interface經(jīng)典實例

需求:
我需要從不同的源收集文本殉农。(可以從遠(yuǎn)程URL讀取HTML,可以讀取流資源局荚,也可以收集終端命令的輸出)

1超凳、定義Documentable接口

實現(xiàn)Documentable接口的任何類都必須實現(xiàn)接口的getId()方法與getContent()方法。

<?php
interface Documentable
{
    public function getId();
    public function getContent();
}

2耀态、定義三種實現(xiàn)方式

定義以上接口的用處是轮傍,我們可以分開定義獲取文檔的類,而且能使用十分不同的實現(xiàn)方式首装。

1)定義HtmlDocument類

<?php
class HtmlDocument implements Documentable
{
    protected $url;
    public function __construct($url)
    {
        $this->url = $url;
    }
    public function getId()
    {
        return $this->url;
    }
    public function getContent()
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
        $html = curl_exec($ch);
        curl_close($ch);
        return $html;
    }
}

2)定義StreamDocument類

<?php
class StreamDocument implements Documentable
{
    protected $resource;
    protected $buffer;
    public function __construct($resource, $buffer = 4096)
    {
        $this->resource = $resource;
        $this->buffer = $buffer;
    }
    public function getId()
    {
        return 'resource-' . (int)$this->resource;
    }
    public function getContent()
    {
        $streamContent = '';
        rewind($this->resource);
        while (feof($this->resource) === false) {
            $streamContent .= fread($this->resource, $this->buffer);
        }
        return $streamContent;
    }
}

3)定義CommandOutputDocument類

<?php
class CommandOutputDocument implements Documentable
{
    protected $command;
    public function __construct($command)
    {
        $this->command = $command;
    }
    public function getId()
    {
        return $this->command;
    }
    public function getContent()
    {
        return shell_exec($this->command);
    }
}

3创夜、定義DocumentStore類

<?php
class DocumentStore
{
    protected $data = [];
    public function addDocument(Documentable $document)
    {
        $key = $document->getId();
        $value = $document->getContent();
        $this->data[$key] = $value;
    }
    public function getDocuments()
    {
        return $this->data;
    }
}

4、使用DocumentStore類

<?php
require 'Documentable.php';
require 'DocumentStore.php';
require 'HtmlDocument.php';
require 'StreamDocument.php';
require 'CommandOutputDocument.php';
$documentStore = new DocumentStore();
// Add HTML document
$htmlDoc = new HtmlDocument('http://php.net');
$documentStore->addDocument($htmlDoc);
// Add stream document
$streamDoc = new StreamDocument(fopen('stream.txt', 'rb'));
$documentStore->addDocument($streamDoc);
// Add terminal command document
$cmdDoc = new CommandOutputDocument('cat /etc/hosts');
$documentStore->addDocument($cmdDoc);
print_r($documentStore->getDocuments());

總結(jié):

使用接口編寫的代碼更靈活簿盅,能委托別人實現(xiàn)細(xì)節(jié)挥下。使用接口后會有起來越多的人使用你的代碼,因為他們只需要知道如何實現(xiàn)接口桨醋,就可以無縫地使用你的代碼棚瘟。

源碼地址:https://github.com/codeguy/modern-php/tree/master/02-features/interfaces

五、參考

《Modern PHP》Josh Lockhart 著 安道 譯

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喜最,一起剝皮案震驚了整個濱河市偎蘸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞬内,老刑警劉巖迷雪,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異虫蝶,居然都是意外死亡章咧,警方通過查閱死者的電腦和手機(jī)我碟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門涕烧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來国瓮,“玉大人,你說我怎么就攤上這事押赊『ッ常” “怎么了辞州?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵逃贝,是天一觀的道長。 經(jīng)常有香客問我程剥,道長劝枣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任织鲸,我火速辦了婚禮舔腾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昙沦。我一直安慰自己琢唾,他們只是感情好载荔,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布盾饮。 她就那樣靜靜地躺著,像睡著了一般懒熙。 火紅的嫁衣襯著肌膚如雪丘损。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天工扎,我揣著相機(jī)與錄音徘钥,去河邊找鬼。 笑死肢娘,一個胖子當(dāng)著我的面吹牛呈础,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播橱健,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼而钞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拘荡?” 一聲冷哼從身側(cè)響起臼节,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎珊皿,沒想到半個月后网缝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蟋定,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年粉臊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驶兜。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡扼仲,死狀恐怖果元,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情犀盟,我是刑警寧澤而晒,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站阅畴,受9級特大地震影響倡怎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贱枣,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一监署、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纽哥,春花似錦钠乏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至只壳,卻和暖如春俏拱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吼句。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工锅必, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惕艳。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓搞隐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親远搪。 傳聞我的和親對象是個殘疾皇子劣纲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容