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

时间:2011-03-01 22:51:57

标签: 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();
   }
}

正如您在上面的代码中所看到的,记录器类期望其模块能够同时运行error()ssh_for_recorder(),但这些是由不同的接口定义的。不可思议也不需要记录,反之亦然。

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

4 个答案:

答案 0 :(得分:10)

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

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

答案 1 :(得分: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");
    }
}

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

interface foobar extends foo,bar{}

然后你可以只需要foobar方法。

答案 2 :(得分: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
}

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

在你的情况下,如果你想要一个既错误又可记录的东西,那么你只需要添加以下界面:

interface RecordableErrorable extends Recordable, Errorable { }

然后你的Recorder类的构造函数只是期望接口作为它的参数。

public function __construct(RecordableErrorable $module) { }

如果Recordable和Errorable都实现了具有相同名称的方法,那么可能存在一个可能的问题。那里会发生冲突,需要解决。我相信PHP中有处理这种情况的机制,虽然我无法告诉你它们是什么。

答案 3 :(得分: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();
}
相关问题