【问题标题】:Interface implementation: declaration must be compatible接口实现:声明必须兼容
【发布时间】:2013-10-08 11:55:09
【问题描述】:

我有接口:

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 不支持真正的函数/方法重载,就像您可能习惯的其他语言(例如 Java、C++)一样。

标签: php oop inheritance interface


【解决方案1】:

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

当然,您总是可以手动签入代码:

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

【讨论】:

  • 但我尝试在此基础上创建另一个界面。不实现,但有限制地继承。
  • 扩展还是实现并不重要。您不能更改接口声明,句号。当 Bar 的实现比 Foo 指定的限制更多时,你不能说 Foo 实现了 Bar。
【解决方案2】:

另一种实现方式是:

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

    private function convert(Product $var)
    {
        ...
    }
}

【讨论】:

    【解决方案3】:

    在 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 类,因为接口上任何合法的东西都是在实现上也有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-20
      • 1970-01-01
      • 2012-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多