使用具体类型类实现具有接口类型提示的抽象方法


Implements a abstract method with interface type hint with a concrete typing class

这里有一个简单的问题,我无法解释。

在 PHP 手册中:

如果类或接口被指定为类型提示,则也允许其所有子项或实现。

我记得这是一个抽象方法的情况,但在我看来,它就像"没有逻辑"。

下面是一个示例:

我搜索如何通过以下方式实现方法(在本例中为调用(:

<?php
namespace Foo'Bundle'BarBundle;
abstract class BaseClass {
    //...
    abstract public function invoke(AddContactCommandInterface $command);
}
<?php
namespace Foo'Bundle'UpBarBundle;
use Foo'Bundle'BarBundle'BaseClass;
class UpClass extends BaseClass
{
    public function invoke(AddContactCommand $command)
    {
        //...
    }
}

AddContactCommand 实现了 AddContactCommandInterface !

我有这个问题

声明必须与 BaseClass->invoke(AddContactCommandInterface( 兼容

有人可以向我解释为什么不可能在PHP 5.6中进行这种基本和逻辑操作?

抽象方法定义所有派生类都需要实现的函数。 在定义抽象方法时,您说它需要一个AddContactCommandInterface,然后在您的子类中将其更改为AddContactCommand。 您正在更改在 Abstract 类中指定的"协定"。

AddContactCommand实现接口并不重要。 并非所有AddContactCommandInterfaces都是AddContactCommands

从使用的角度来看,如果允许这样做,它会导致困难,因为我可以有一个期望使用BaseClass对象的方法。 我有一个不同的对象Foo来实现AddContactCommandInterface. 现在,我的方法获取UpClass的实例,并尝试使用传入Foo对象的invoke方法。 这将导致致命错误,即使根据我对 Abstract 类中指定的协定的理解,我应该能够使用我的 Foo 对象。 混乱和集体歇斯底里接踵而至。

这不是逻辑问题,而是一致性问题。 如果您确实想键入提示AddContactCommand请更改抽象方法。 但是,如果您打算使用实现AddContactCommandInterface的所有内容,请更改派生类。

BaseClass声明任何子类都必须具有名为 invoke 的公共方法,该方法接受实现AddContactCommandInterface的任何对象。

UpClass不能满足此要求。它的调用函数只接受AddContactCommand或子对象的具体实例。

如果允许代码,则以下内容将失败:

class SomeOther implements AddContactCommandInterface
{
    //implementation of interface
}
$up = new UpClass();
$up->invoke(new SomeOther());

为什么不让UpClass->invoke接受接口的实现呢?您仍然可以通过混凝土AddContactCommand

在第二个类中,您将重写 BaseClass;invoke 方法---

这要求子类中的 invoke 方法接受相同的参数 -

在本例中,您已经键入暗示 argumen,$command 属于 AddContactCommandInterface --- 类型,但是,在您的子类中,您提出了参数AddContactCommand

因此,您可以通过使基类中的$command与子类中的$command类型相同来修复它,反之亦然。