我們專注于高端品牌網(wǎng)站創(chuàng)意設計與開發(fā)
大家好,在這里【源美設計】就和大家一起談下關于對PHP接口的思考,我們在PHP的接口自始至終一直在被爭議,有人說接口很好,有人說接口像雞肋。首先要明白,好和不好的判斷標準是什么。無疑,這是和Java/C++相比。在上面的例子中,已經(jīng)討論了PHP的接口在“面向契約編程”中是不足的,并沒有起到應有的作用。
其實,在上面的interface.php代碼中,machine類的聲明應該在plain類前面。接口提供了一套規(guī)范,這是系統(tǒng)提供的,然后machine類提供一組針對接口的API并實現(xiàn),最后才是自定義的類。在Java里,接口之所以盛行(多線程的runable接口、容器的collection接口等)就是因為系統(tǒng)為我們做了前面兩部分的工作,而程序員,只需要去寫具體的實現(xiàn)類,就能保證接口可用可控。
為什么要用接口?接口到底有什么好處?接口本身并不提供實現(xiàn),只是提供一個規(guī)范。如果我們知道一個類實現(xiàn)了某個接口,那么就知道了可以調用該接口的哪些方法,我們只需要知道這些就夠了。
PHP中,接口的語義是有限的,使用接口的地方并不多,PHP中接口可以淡化為設計文檔,起到一個團隊基本契約的作用,代碼如下所示:
<?php
interface cache{
/**
@describe:緩存管理,項目經(jīng)理定義接口,技術人員負責實現(xiàn)
**/
const maxKey=10000;//最大緩存量
public function getc($key);//獲取緩存
public function setc($key,$value);//設置緩存
public function flush();//清空緩存
}
PHP是強調靈活,所以并不推薦大規(guī)模使用接口,而是僅在部分“內核”代碼中使用接口,因為PHP中的接口已經(jīng)失去很多接口應該具有的語義。從語義上考慮,可以更多地使用抽象類。至于抽象類和接口的比較,不再贅述。
另外,PHP5對面向對象的特性做了許多增強,其中就有一個SPL(標準PHP庫)的嘗試。SPL中實現(xiàn)一些接口,其中最主要的就是Iterator迭代器接口,通過實現(xiàn)這個接口,就能使對象能夠用于foreach結構,從而在使用形式上比較統(tǒng)一。比如SPL中有一個DirectoryIterator類,這個類在繼承SplFileInfo類的同時,實現(xiàn)Iterator、Traversable、SeekableIterator這三個接口,那么這個類的實例可以獲得父類SplFileInfo的全部功能外,還能夠實現(xiàn)Iterator接口所展示的那些操作。
Iterator接口的原型如下:
*current()
This method returns the current index's value.You are solely
responsible for tracking what the current 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().
如果一個類聲明了實現(xiàn)Iterator接口,就必須實現(xiàn)這五個方法,如果實現(xiàn)了這五個方法,那么就可以很容易對這個類的實例進行迭代。這里,DirectoryIterator類之所以拿來就能用,是因為系統(tǒng)已經(jīng)實現(xiàn)了Iterator接口,所以可以像下面這樣使用:
<?php
$dir=new DirectoryIterator(dirname(_FILE_));
foreach($dir as$fileinfo){
if(!$fileinfo->isDir()){
echo
$fileinfo->getFilename(),"\t",$fileinfo->getSize(),PHP_EOL;
}
}
可以想象,如果不用DirectoryIterator類,而是自己實現(xiàn),不但代碼量增加了,而且循環(huán)時候的風格也不統(tǒng)一了。如果自己寫的類也實現(xiàn)了Iterator接口,那么就可以像Iterator那樣工作。
為什么一個類只要實現(xiàn)了Iterator迭代器,其對象就可以被用作foreach的對象呢?其實原因很簡單,在對PHP實例對象使用foreach語法時,會檢查這個實例有沒有實現(xiàn)Iterator接口,如果實現(xiàn)了,就會通過內置方法或使用實現(xiàn)類中的方法模擬foreach語句。這是不是和前面提到的_toString方法的實現(xiàn)很像呢?事實上,_toString方法就是接口的一種變相實現(xiàn)。
接口就是這樣,接口本身什么也不做,系統(tǒng)悄悄地在內部實現(xiàn)了接口的行為,所以只要實現(xiàn)這個接口,就可以使用接口提供的方法。這就是接口“即插即用”思想。
我們都知道,接口是對多重繼承的一種變相實現(xiàn),而在講繼承時,我們提到了用來實現(xiàn)混入(Mixin)式的Traits,實際上,Traits可以被視為一種加強型的接口。
來看一段代碼:
<?php
trait Hello{
public function sayHello(){
echo'Hello';
}
}
trait World{
public function sayWorld()
echo'World';
}
}
class MyHelloWorld{
use Hello,World;
public function sayExclamationMark(){
echo'!';
}
}
$o = new MyHelloWorld();
$o ->sayHello();
$o ->sayWorld();
$o ->sayExclamationMark();
?>
上面的代碼運行結果如下:
Hello World!
這里的MyHelloWorld同時實現(xiàn)了兩個Traits,從而使其可以分別調用兩個Traits里的代碼段。從代碼中就可以看出,Traits和接口很像,不同的是Traits是可以導入包含代碼的接口。從某種意義上來說,Traits和接口都是對“多重繼承”的一種變相實現(xiàn)。
總結關于接口的幾個概念:
接口作為一種規(guī)范和契約存在。作為規(guī)范,接口應該保證可用性;作為契約,接口應該保證可控性。
接口只是一個聲明,一旦使用interface關鍵字,就應該實現(xiàn)它??梢杂沙绦騿T實現(xiàn)(外部接口),也可以由系統(tǒng)實現(xiàn)(內部接口)。接口本身什么都不做,但是它可以告訴我們它能做什么。
PHP中的接口存在兩個不足,一是沒有契約限制,二是缺少足夠多的內部接口。
接口其實很簡單,但是接口的各種應用很靈活,設計模式中也有很大一部分是圍繞接口展開的。
文章引用:http://www.xhjcyz.com/new/142.html
本站文章為深圳網(wǎng)站建設·源美網(wǎng)絡原創(chuàng)策劃,如有版權糾紛或者違規(guī)問題,請聯(lián)系我們刪除,謝謝!
上一篇: 電源里的病毒
售后保障
承諾任何問題1小時內解決數(shù)據(jù)備份
更安全、更高效、更穩(wěn)定價格公道精準
項目經(jīng)理精準報價不弄虛作假合作無風險
重合同講信譽,無效全額退款