【问题标题】:Is it possible to define method with different parameters in a PHP interface?是否可以在 PHP 接口中定义具有不同参数的方法?
【发布时间】:2012-12-07 20:37:22
【问题描述】:

我正在开发一个注入 Logger 对象的服务,但我可以拥有 2 种不同类型的记录器,我计划拥有一个 syslog 记录器和一个队列消息系统记录器。这可能吗?

这个想法是有一个界面:

interface Loggable
{
    public function log() ;
}

以及实现该接口的 2 个类:

class Syslogger implements Loggable
{
    public function log()
    {
        ...
    }
}

class QMSLogger implements Loggable
{
    public function log($queueName)
    {
        ...
    }
}

我能想到的唯一方法是将数组作为参数并在一个类上使用它而不在另一个类上使用......但这有点臭:P

【问题讨论】:

  • 如果方法在一种情况下接受一个参数而在另一种情况下不接受,那就不是同一个接口!
  • 是的,我想这是更正确的方法,但我希望能够注入任何一个类来更改日志系统......我想我错了
  • 好吧,如果$queueName 默认为 NULL (public function log($queueName = null) {...}),这实际上是可能的,但我同意这里的 deceze。

标签: php interface dependency-injection


【解决方案1】:

我遇到了一个类似的案例,我想创建一个接口,它只是确保实现它的任何类都有一个同名的方法,但允许使用不同的参数实现。

/**
 * Interface Loggable
 * @method log
 */
interface Loggable
{

}

现在可以使用不同的参数来实现 Loggable 接口。

class Syslogger implements Loggable
{
    public function log($key, $value)
    {
        ...
    }
}

【讨论】:

  • 这实际上是最好的答案(恕我直言)。这种类型的模式称为duck typing。它理想地用于 IoC 容器和服务管理器中的实例化例程期间的“自动连接”。空接口只是告诉容器在实例化后调用特定方法,同时让依赖注入器 (DI) 通过类型提示确定要注入的参数。从技术上讲,空接口是可选的,但有助于防止 DI 容器调用第三方库中的同名方法是一种很好的做法。
【解决方案2】:

您也可以将参数作为数组传递,这样您一方面尊重合同,还可以灵活地在数组中插入任意数量的任何值,看看这个:

abstract class FeaturesAbstract
{
    /**
     * @param array $paramsArray
     *
     * @return mixed
     */
    abstract public function addExecute($paramsArray);
}

要实际使用此方法,您可以像这样发送参数:

$this->abstract->addExecute(array('paramA' => $paramA, 'paramB' =>  $paramB));

然后在具体的实现中你会得到这样的参数:

    /**
     * @param array $paramsArray
     *
     * @return void
     */
    public function addExecute($paramsArray) 
    {
        $a = $paramsArray['paramA'];
        $b = $paramsArray['paramB'];
        $c = ...
    }

祝你好运:)

【讨论】:

    【解决方案3】:

    你问是否有可能:是的,但是……

    如果你实现一个接口,你必须尊重它的契约

    interface Loggable
    {
        public function log();
    }
    

    这个接口的合约是你可以不带任何参数调用log()

    为了尊重这一点,您可以将参数设为可选:

    class QMSLogger implements Loggable
    {
        public function log($queueName = null)
        {
            ...
        }
    }
    

    这是perfectly valid PHP,它尊重里氏替换原则。当然,在针对接口编码时不能使用该可选参数,否则你显然会破坏接口。此类参数仅在您使用实现时才有用(例如,在与QMSLogger 紧密耦合的代码的某些部分中)。

    但是,这可能不是您问题的解决方案,因为 $queueName 似乎是一个配置值,最好将它传递给类的构造函数(如另一个答案中所述)。

    【讨论】:

      【解决方案4】:

      正如 cmets 中所述,这不是 相同的界面。如果您无法在所有可能的记录器实现中通用接口,请将配置差异作为实例构造函数的一部分:

      class QMSLogger implements Loggable {
      
          protected $queueName;
      
          public function __construct($queueName) {
              $this->queueName = $queueName;
          }
      
          public function log() {
              ...
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-10
        • 1970-01-01
        • 2013-02-02
        • 1970-01-01
        • 2016-02-26
        • 2010-09-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多