對php介面使用問題的一些總結

來源:互聯網
上載者:User
PHP的介面自始至終一直在被爭議,有人說介面很好,有人說介面像雞肋。首先要明白,好喝不好的判斷標準是什麼。無疑,這是和Java/C++相比。在上面的例子中,以及討論了PHP的介面在“面向契約編程”中是不足的,並沒有起到應有的作用。

其實,machine類的聲明應該在plain類前面。介面提供了一套規範,這是系統提供的,然後machine類提供一組針對介面的API並實現,最後才是自訂的類。在Java裡,介面之所以盛行(多線程的runable介面,容器的collection介面等)就是因為系統為我們做了前面兩部分的工作,而程式員,只需要去寫具體的實作類別,就能保證介面可用可控。

為什麼要用介面?介面到底有什麼好處?介面本身並不提供實現,只是提供一個規範。如果我們知道一個類實現了某個介面,那麼就知道了可以調用該介面的那些方法,我們只需要知道這些就夠了。

PHP中,介面的語義是有限的,使用介面的地方並不多,PHP中介面可以淡化為設計文檔,起到一個團隊基本契約的作用,代碼如下所示:

<?phpinterface Cache{/** * describe:緩衝管理,專案經理定義介面,技術人員負責實現 */    const maxKey = 10000;                  //最大換存量    public function getCache($key);        //擷取緩衝    public function setCache($key,$value); //設定緩衝    public function flush();               //清空緩衝}


由於PHP是弱類型,且強調靈活,所並不推薦大規模使用介面,而是僅在部分“核心”代碼中使用介面,因為PHP中的介面已經失去很多介面應該具有的語義。從語義上考慮,可以更多地使用抽象類別。至於抽象類別和介面的比較,不再贅述。

另外,PHP5對物件導向的特種做了許多增強,其中就有一個SPL(標註PHP庫)的嘗試,SPL中實現一些介面,其中最主要的就是iterator迭代器介面,通過實現這個介面,就能使對象能用於foreach結構,從而在使用形式上比較統一。比如SPL中一個DirectoryIterator類,這個類在整合SplFileInfo類的同時,實現Iterator、Traversable、SeekableIterator這三個介面,那麼這個類的執行個體可以獲得父類SplFileInfo的全部功能外,還能夠實現Iterator介面所展示的那些操作。

Iterator介面的原型如下:

* current()    This methodreturns the current index's value. You are solely responsible for tracking what thecurrent index is as the interface does not do this for you.*key()    This method returns the value of the current index's key. For foreach loops this is extremely important so that the key value can be populated.    *next()    This method moves the internal index forward one entry.    *rewind()    This method should reset the internal index to the first element.*valid()    This method should return true or false if there is a current element. It is called after rewind() or next().

如果一個類聲明了實現Iterator,就必須實現這五個方法,如果實現了這五個方法,那麼就可以很容易對這個類的執行個體進行迭代。這裡,DirectoryIterator類之所以拿來就能用,是因為系統已經實現了Iterator介面,所以可以像下面這樣使用:

<?php$dir = new DirectoryIterator(dirname(FILE));foreach ($dir as $fileInfo){    if(!$fileInfo->isDir())    {        echo $fileInfo->getFilename(),"\t",$fileInfo->getSize(),PHP_EOL;    }}

可以想象,如果不用DirectoryIterator類,而是自己實現,不但代碼量增加了,而且迴圈時候的風格也不統一了。如果自己寫的類也實現了Iterator介面,那麼就可以像Iterator那樣工作。

為什麼一個類只要實現了Iterator迭代器,其對象就可以被用做foreach的對象呢?其實原因很簡單,在對PHP執行個體對象使用foreach文法時,會檢查這個執行個體有沒有實現Iterator介面,如果實現了,就會通過內建方法或使用實作類別中的方法類比foreach語句,這是不是和前面提到的toString 方法的實現很像呢?事實上,toString方法就是介面的一種變相實現。介面就是這樣,介面本身什麼也不做,系統悄悄地在內部實現了介面的行為,所以只要實現這個介面,就可以使用介面提供的方法。這就是介面“隨插即用”思想

我們都知道,介面是多多重整合的一種變相實現,而在講繼承時,我們提到了用來實現混入(Minxin)式的Traits,實際上,traits可以被視為一種加強版的介面。

來看下面的代碼:

<?phptrait Hello{    public function sayHello()    {        echo 'Hello ';    }}trait World{    public function sayWorld()    {        echo 'Word';    }}class MyHelloWorld{    use Hello, World;    public function sayExclamationMark()    {        echo '!';    }}$o = new MyHelloWorld();$o->sayHello();$o->sayWorld();$o->sayExclamationMark();

上面代碼運行結果如下:

Hello Word!

這裡的MyHelloWorld同時實現了兩個traits,從而使其可以分別調用兩個Traits裡的程式碼片段。從代碼中就可以看出,Traits和介面很像,不同的是Traits是可以匯入包含代碼的介面。從某種意義上來說,Traits和介面都是對“多重整合”的一種變相實現。

總結關於介面的幾個概念:

  • 介面作為一種規範和契約存在。作為規範,介面應該保證可用性;作為契約介面應該保證可控性、

  • 介面只是一個聲明,一旦使用interface關鍵字,就應該實現它。可以由程式員實現(外部介面),也可以由系統實現(內部介面)。介面本身什麼都不做,但是他可以高數我們它能做什麼。

  • PHP中的介面存在兩個不足,一時沒有契約限制,二是缺少足夠多的內部介面。

介面其實很簡單,但是介面的各種應用很靈活,設計模式中也有很大一部分是圍繞介面展開的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.