接口实现:声明必须兼容


Interface implementation: declaration must be compatible

我有接口:

interface AbstractMapper
{
    public function objectToArray(ActiveRecordBase $object);
}

和类:

class ActiveRecordBase
{
   ...
}
class Product extends ActiveRecordBase
{
   ...
}
===

=====

但我不能这样做:

interface ExactMapper implements AbstractMapper
{
    public function objectToArray(Product $object);
}

或者这个:

interface ExactMapper extends AbstractMapper
{
    public function objectToArray(Product $object);
}

我收到错误"声明必须兼容"

有没有办法在 PHP 中做到这一点?

不,接口必须精确实现。如果将实现限制为更具体的子类,则它不是相同的接口/签名。PHP 没有泛型或类似的机制。

当然,您始终可以手动签入代码:

if (!($object instanceof Product)) {
    throw new InvalidArgumentException;
}

在 7.4 之后,当添加了对协方差和逆变的支持时,您无法执行预期操作,但可以执行完全相反的操作。

逆变意味着参数类型在子方法中的特异性可能低于其父方法或接口的参数类型。

例如,给定以下两个类:

class Foo {}
class FooChild extends Foo {}

和这样的界面

interface A {
    public function a(FooChild $f): Foo;
}

你可以有一个实现:

class AI implements A {
    public function a(Foo $f): Foo
    {
        return $f;
    }
}

虽然实现不完全遵循接口,但它是兼容的,因为A接口的任何使用者仍然可以安全地使用 AI 类,因为接口上合法的任何内容在实现上也有效。

实现这一点的另一种方法是:

class Executor
{
    public function objectToArray(AbstractMapper $var)
    {
        $this->convert($var);
    }
    private function convert(Product $var)
    {
        ...
    }
}