2011-03-01 50 views
7

有沒有辦法在PHP中鍵入提示兩個不同的,不相關的接口?例如:類型提示多個不相關的接口

interface errorable { 
    function error($msg); 
} 

interface recordable { 
    ssh_for_recorder(); 
} 

class uploader__module extends base__module implements errorable, recordable { 
    public function ssh_for_recorder() { 
     return new ssh2; 
    } 
    public function error($msg) { 
     $this->errors[] = $msg; 
    } 

    public function upload() { 
     $recorder = new recorder($this); 
     $recorder->run(); 
    } 
} 

class recorder { 
    private $ssh2; 
    private $module; 
    private function upload() { 
     if (!$this->ssh2) { 
     $this->module->error("No SSH2 connection"); 
     } 
    } 
    public function __construct({recordable,errorable} $module) { 
     $this->module = $module; 
     $this->ssh2 = $module->ssh_for_recorder(); 
    } 
} 

正如你可以在上面的代碼中看到,記錄類預計其模塊必須同時運行error()ssh_for_recorder(),但這些是由不同的接口定義的能力。錯誤的需要不可記錄,反之亦然。

是否有這樣做的最佳做法?我正在考慮創建一個接口,該接口從可記錄和可錯誤的方面擴展並具有upload__module實現,但我不知道該怎麼稱呼它。

+0

這與鍵入提示有什麼關係? – Hamish 2011-03-01 23:11:37

+1

請參閱記錄器的構造函數。我想輸入提示可錄和可錯。 – 2011-03-01 23:16:34

+0

我認爲@Hammish越來越困惑,PHP中的類型提示需要一個類爲某種類型,其中@tandu需要檢查多種類型的接口。 – RobertPitt 2011-03-01 23:58:00

回答

10

不,這是不可能在PHP中。

還有其他支持此功能的語言(主要是功能),稱爲聯合類型(http://en.wikipedia.org/wiki/Sum_type)。

+0

你會如何建議在PHP中解決這個問題? – 2011-03-01 23:44:12

+0

好吧,製作一個新的界面,可擴展可記錄和易錯。但是,您將不得不改變實現兩個接口的類來實現新接口。 – linepogl 2011-03-01 23:50:39

+0

正如我的想法。我結束了可記錄的擴展錯誤,以至於在我的應用程序中也解決了這個問題。 # – 2011-03-02 01:01:56

6

PHP中的唯一黑客是一個輔助功能做檢查你的方法中,像這樣:

function CheckInterfaces($object,array $interfaces) 
{ 
    foreach($interfaces as $i) 
    { 
     if(!is_a($object,$i)) 
     { 
      return false; 
     } 
    } 
    return true; 
} 

然後在方法中做:

public function Something($object) 
{ 
    if(CheckInterfaces($object,array("foo","bar"))) 
    { 
     throw new ArgumentException(gat_class($object) . " Must be a member of foo,bar to be passed to Something"); 
    } 
} 

解決此另一種方法發行ius爲您的所需接口創建聯合接口,繼承人快速示例

interface foobar extends foo,bar{} 

那麼你可以只需要foobar這個方法。

+1

#1很有趣,但我認爲它會過度。我更喜歡#2。但請注意,接口擴展了其他接口,但它們並未實現它們。你的代碼會導致語法錯誤。 – 2011-03-02 01:01:20

+0

那裏的小監督。 – RobertPitt 2011-03-02 07:51:02

+1

儘管這是唯一合理的解決方案,但我不喜歡2,因爲我還必須更改類來實現聯合界面,而不是單獨的界面 – bencoder 2014-07-17 11:58:28

0
public function __construct(recordable $recordable_module, errorable $errorable_module) { 

    if($recordable_module == $errorable_module){ 
    $module = $recordable_module; 
    } 
    $this->module = $module; 
    $this->ssh2 = $module->ssh_for_recorder(); 
} 
2

即使您已經接受答案,我已決定回答這個問題,理由是沒有給出的答案是真的可以接受的。雖然接受的答案在技術上是正確的,但有一種解決方法。至於其他答案,他們的解決方法不夠優雅,並不完全令人滿意。

PHP支持一個相當模糊的特性,允許一個接口從另一個接口繼承,實際上一個接口能夠從多個基接口繼承。

例如,以下是完全有效的:

interface iFoo 
{ 
    public function doFoo(); 
} 

interface iBar 
{ 
    public function doBar(); 
} 

interface iBaz extends iFoo, iBar 
{ 
    // This interface implicitly has all the methods of iFoo and iBar 
} 

語義上說,如果你想有一個方法/函數只接受一個實現多個接口,那麼一個參數,往往會建議你想到的是類,實現同一組多個接口實際上應該實現一個接口,該接口涵蓋了希望參數符合的兩個接口。

在你的情況,如果你想要的東西,既是errorable和記錄的,那麼你只需要添加以下接口:

interface RecordableErrorable extends Recordable, Errorable { } 

然後構造你的錄音機類只會想到界面它的論點。

public function __construct(RecordableErrorable $module) { } 

如果Recordable和Errorable都實現了同名的方法,那麼可能存在一個棘手的問題。那裏會有衝突,需要解決。我相信PHP中有處理這種情況的機制,但我無法告訴你它們是什麼。