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

kqlmhetl  于 2023-11-16  发布在  PHP
关注(0)|答案(5)|浏览(163)

在php中有没有一种方法可以为两个不同的、不相关的接口输入hint?例如:

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

字符串
正如你在上面的代码中所看到的,recorder类希望它的模块能够同时运行error()ssh_for_recorder(),但是它们是由不同的接口定义的。
有没有一个最好的实践来做到这一点?我想创建一个接口,从可记录和可出错扩展,并有upload__模块实现,但我不知道该怎么称呼它。

sigwle7e

sigwle7e1#

这在PHP中是不可能的。
还有其他语言(大多数是函数式的)支持这种特性,称为联合类型(http://en.wikipedia.org/wiki/Sum_type)。

pkbketx9

pkbketx92#

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就可以了。

ogq8wdun

ogq8wdun3#

我决定回答这个问题,即使你已经接受了一个答案,理由是没有一个答案是真正可以接受的。虽然接受的答案在技术上是正确的,但有一种方法可以绕过它。至于其他答案,他们的变通方法是不优雅的,并不完全令人满意。
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和Erroable是否都实现了同名的方法。这将是一个需要解决的冲突。我相信PHP中有处理这种情况的机制,尽管我不能告诉你它们是什么。

rjzwgtxy

rjzwgtxy4#

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

字符串

vojdkbi0

vojdkbi05#

我知道这是旧的,但有一些变化的PHP。PHP8.2现在支持析取范式类型https://wiki.php.net/rfc/dnf_types
public function __construct(Recordable & Errorable $module)这样的东西是可能的。

相关问题