是否可以在PHP接口中定义具有不同参数的方法?


Is it possible to define method with different parameters in a PHP interface?

我正在开发一个正在注入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

你问这是否可能:是的,它是,但是…

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

interface Loggable
{
    public function log();
}

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

为了尊重这一点,你可以使参数可选:

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

这是完全有效的PHP,它尊重Liskov替换原则。当然,在对接口进行编码时,不能使用这个可选参数,否则显然会破坏接口。这样的参数只有在使用实现时才有用(例如,在代码的某些部分与QMSLogger紧密耦合)。

然而,这可能不是你的问题的解决方案,因为$queueName似乎是一个配置值,它可能会更好地传递它在类的构造函数(如在另一个答案中解释的)。

如评论所述,这不是相同的界面。如果您不能在所有可能的日志记录器实现中泛化接口,请将配置差异作为实例构造函数的一部分:

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

我遇到过一个类似的情况,我想创建一个接口,简单地确保实现它的任何类都有一个同名的方法,但允许使用不同的参数实现。

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

现在可以使用不同的参数实现Loggable接口,如下所示

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

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

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 = ...
    }

祝你好运