严格标准:childClass::customMethod() 的声明应该与 parentClass::customMethod() 的声明兼容
PHP中此错误的可能原因是什么?我在哪里可以找到关于兼容意味着什么的信息?
严格标准:childClass::customMethod() 的声明应该与 parentClass::customMethod() 的声明兼容
PHP中此错误的可能原因是什么?我在哪里可以找到关于兼容意味着什么的信息?
childClass::customMethod()
与 . 相比,具有不同的参数或不同的访问级别(公共/私有/受保护)parentClass::customMethod()
。
此消息意味着某些可能的方法调用可能会在运行时失败。假设你有
class A { public function foo($a = 1) {;}}
class B extends A { public function foo($a) {;}}
function bar(A $a) {$a->foo();}
编译器仅根据不需要参数的 A::foo() 的要求检查调用 $a->foo()。但是,$a 可能是需要参数的 B 类对象,因此调用将在运行时失败。
但是,这永远不会失败并且不会触发错误
class A { public function foo($a) {;}}
class B extends A { public function foo($a = 1) {;}}
function bar(A $a) {$a->foo();}
所以没有一个方法可能比它的父方法有更多的必需参数。
当类型提示不匹配时也会生成相同的消息,但在这种情况下 PHP 的限制更大。这给出了一个错误:
class A { public function foo(StdClass $a) {;}}
class B extends A { public function foo($a) {;}}
就像这样:
class A { public function foo($a) {;}}
class B extends A { public function foo(StdClass $a) {;}}
这似乎比它需要的限制更多,我认为这是由于内部原因。
可见性差异会导致不同的错误,但基本原因相同。没有任何方法比它的父方法更显眼。
如果您想保持 OOP 形式而不关闭任何错误,您还可以:
class A
{
public function foo() {
;
}
}
class B extends A
{
/*instead of :
public function foo($a, $b, $c) {*/
public function foo() {
list($a, $b, $c) = func_get_args();
// ...
}
}
只是为了在接口的上下文中扩展此错误,如果您正在键入提示您的函数参数,如下所示:
接口A
use Bar;
interface A
{
public function foo(Bar $b);
}
B类
class B implements A
{
public function foo(Bar $b);
}
如果您忘记use
在您的实现类(B 类)中包含该语句,那么即使方法参数相同,您也会收到此错误。
我在尝试从 GitHub 扩展现有类时遇到了这个问题。我将尝试解释自己,首先按照我应该的方式编写课程,然后按照现在的方式编写课程。
我虽然
namespace mycompany\CutreApi;
use mycompany\CutreApi\ClassOfVendor;
class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
public function whatever(): ClassOfVendor
{
return new ClassOfVendor();
}
}
我终于做了什么
namespace mycompany\CutreApi;
use \vendor\AwesomeApi\ClassOfVendor;
class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
public function whatever(): ClassOfVendor
{
return new \mycompany\CutreApi\ClassOfVendor();
}
}
因此,当您使用返回命名空间类的方法并且您尝试返回相同的类但使用其他命名空间时,似乎也会引发此错误。幸运的是我找到了这个解决方案,但我并不完全理解这个特性在 php 7.2 中的好处,对我来说,根据需要重写现有的类方法是正常的,包括重新定义输入参数和/甚至行为方法。
前一种方法的一个缺点是 IDE 无法识别在 \mycompany\CutreApi\ClassOfVendor() 中实现的新方法。所以,现在,我将使用这个实现。
目前完成
namespace mycompany\CutreApi;
use mycompany\CutreApi\ClassOfVendor;
class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
public function getWhatever(): ClassOfVendor
{
return new ClassOfVendor();
}
}
因此,我没有尝试使用“whatever”方法,而是编写了一个名为“getWhatever”的新方法。事实上,它们都在做同样的事情,只是返回一个类,但正如我之前描述的那样,它们具有不同的命名空间。
希望这可以帮助某人。