这是一个我无法解释的简单问题。
在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-&gt; invoke(AddContactCommandInterface)兼容
有人可以向我解释为什么在PHP 5.6
中无法进行这种基本和逻辑操作?
答案 0 :(得分:2)
抽象方法定义了一个所有派生类需要实现的函数。在定义抽象方法时,您说它需要AddContactCommandInterface
,然后在您的子类中将其更改为AddContactCommand
。您正在更改Abstract类中指定的“合同”。
AddContactCommand
实现接口并不重要。并非所有AddContactCommandInterfaces
都是AddContactCommands
。
从使用的角度来看,如果允许这样做会导致困难,因为我可能有一个期望使用BaseClass
对象的方法。我有一个实现Foo
的不同对象AddContactCommandInterface
。现在我的方法获取了UpClass
的实例,并尝试使用传递在我的invoke
对象中的Foo
方法。这将导致致命错误,即使从我对Abstract类中指定的合同的理解,我应该能够使用我的Foo
对象。随之而来的是混乱和大规模的歇斯底里。
这不是逻辑问题,而是一致性问题。如果您确实要键入提示AddContactCommand
,请更改抽象方法。但是如果您打算可以使用实现AddContactCommandInterface
的所有内容,那么请更改派生类。
答案 1 :(得分:1)
BaseClass
声明任何子类都必须有一个名为invoke的公共方法,它接受任何实现AddContactCommandInterface
的对象。
UpClass
并未满足此要求。
它的invoke函数只接受AddContactCommand
或子对象的具体实例。
如果允许您的代码,以下内容将失败:
class SomeOther implements AddContactCommandInterface
{
//implementation of interface
}
$up = new UpClass();
$up->invoke(new SomeOther());
为什么不让UpClass->invoke
接受接口的实现?您仍然可以传递具体的AddContactCommand
答案 2 :(得分:0)
在你的第二堂课中,你将覆盖BaseClass; s invoke
方法---
这要求子类中的invoke
方法接受相同的参数 -
在这种情况下,你有类型暗示争论者$command
的类型为AddContactCommandInterface
---但是,在你的子类中,你创建了参数AddContactCommand
因此,您可以通过使基类中的$command
与子类中的$command
类型相同来修复它,反之亦然。