【问题标题】:Type Hinting For Multiple Unrelated Interfaces多个不相关接口的类型提示
【发布时间】:2011-07-06 21:25:07
【问题描述】:

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(),但它们是由不同的接口定义的。 errorable 不一定是可记录的,反之亦然。

是否有执行此操作的最佳做​​法?我正在考虑创建一个从可记录和可错误扩展的接口并让 upload__module 实现它,但我不知道该怎么称呼它。

【问题讨论】:

  • 这与类型提示有什么关系?
  • 查看记录器的构造函数。我想输入既可记录又可出错的提示。
  • 我认为@Hammish 很困惑,PHP 中的类型提示要求类是某种类型,而@tandu 需要检查多种类型的接口。

标签: php oop interface type-hinting


【解决方案1】:

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

还有其他语言(主要是函数式)支持这种称为联合类型 (http://en.wikipedia.org/wiki/Sum_type) 的特性。

【讨论】:

  • 你建议如何在 PHP 中解决这个问题?
  • 好吧,创建一个既可记录又可出错的新界面。但是,您必须更改实现这两个接口的类来实现新接口。
  • 如我所想。我最终得到了可记录的扩展错误,因此在我的应用程序中也解决了。
【解决方案2】:

PHP 中唯一的 hack 是一个辅助函数,可以在方法中为您执行检查,如下所示:

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 用于该方法。

【讨论】:

  • #1 很有趣,但我认为它太过分了。我更喜欢#2。不过,请注意,接口扩展了其他接口,它们不实现它们。您的代码将导致语法错误。
  • 虽然这是唯一合理的解决方案,但我不喜欢2,因为我还必须更改类来实现联合接口,而不是单独的单独接口
  • 它是#2。就是这样。
【解决方案3】:

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

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 中有处理这种情况的机制,尽管我不能告诉你它们是什么。

【讨论】:

    【解决方案4】:
    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();
    }
    

    【讨论】:

      猜你喜欢
      • 2011-06-01
      • 2021-05-11
      • 1970-01-01
      • 2014-09-10
      • 2021-11-17
      • 2016-01-19
      • 2023-03-27
      • 1970-01-01
      • 2021-05-16
      相关资源
      最近更新 更多