首頁 >後端開發 >php教程 >對php介面使用問題的一些總結

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

伊谢尔伦
伊谢尔伦原創
2017-07-03 10:40:551627瀏覽

PHP的介面自始至終一直被爭議,有人說接口很好,有人說接口像雞肋。首先要明白,好喝不好的判斷標準是什麼。無疑,這是和Java/C++相比。在上面的例子中,以及討論了PHP的介面在「面向契約程式設計」中是不足的,並沒有起到應有的作用。

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

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

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

<?php
interface 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&#39;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&#39;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可以被視為一種加強版的介面。

來看下面的程式碼:

<?php

trait Hello
{
    public function sayHello()
    {
        echo &#39;Hello &#39;;
    }
}

trait World
{
    public function sayWorld()
    {
        echo &#39;Word&#39;;
    }
}

class MyHelloWorld
{
    use Hello, World;
    public function sayExclamationMark()
    {
        echo &#39;!&#39;;
    }
}

$o = new MyHelloWorld();

$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();

上面程式碼運行結果如下:

Hello Word!

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

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

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

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

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

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

以上是對php介面使用問題的一些總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn