类型提示多个不相关的接口

Exp*_*lls 7 php oop interface type-hinting

在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();
   }
}
Run Code Online (Sandbox Code Playgroud)

正如你可以在上面的代码中看到,记录类预计其模块必须同时运行的能力error()ssh_for_recorder(),但这些是由不同的接口定义.不可能是不可记录的,反之亦然.

这样做有最好的做法吗?我正在考虑创建一个从可记录和错误扩展的接口,并具有upload__module实现,但我不知道该怎么称呼它.

lin*_*ogl 10

不,这在php中是不可能的.

还有其他支持此功能的语言(主要是功能性的)称为联合类型(http://en.wikipedia.org/wiki/Sum_type).


Rob*_*itt 6

PHP中唯一的hack是一个帮助函数,可以在方法中为你做检查,如下所示:

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

然后在方法内做:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

围绕这个问题的另一种方法是为所需的接口创建一个联合接口,这是一个快速的例子

interface foobar extends foo,bar{}
Run Code Online (Sandbox Code Playgroud)

那么你可以只需要foobar这个方法.


Gor*_*onM 5

我决定回答这个问题,尽管您已经接受了答案,因为给出的答案都不是真正可以接受的。虽然接受的答案在技术上是正确的,但有一种方法可以解决它。至于其他答案,他们的解决方法不优雅且不完全令人满意。

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
}
Run Code Online (Sandbox Code Playgroud)

从语义上讲,如果您希望方法/函数仅接受实现多个接口的参数,那么这往往表明您期望实现同一组多个接口的类实际上应该实现一个涵盖您的两个接口的接口。希望你的论点符合。

在您的情况下,如果您想要既可出错又可记录的内容,那么您只需添加以下接口:

interface RecordableErrorable extends Recordable, Errorable { }
Run Code Online (Sandbox Code Playgroud)

然后 Recorder 类的构造函数将简单地期望该接口作为其参数。

public function __construct(RecordableErrorable $module) { }
Run Code Online (Sandbox Code Playgroud)

一个可能的症结在于 Recordable 和 Errorable 是否都实现了同名的方法。那里将会发生需要解决的冲突。我确实相信 PHP 中有处理这种情况的机制,尽管我无法告诉你它们是什么。