方法声明应与PHP中的父方法兼容


107
严格标准:childClass :: customMethod()的声明应与parentClass :: customMethod()的声明兼容

PHP中此错误的可能原因是什么?在哪里可以找到有关兼容的信息


notJim完全正确。@ waiwai933,如果您可以function customMethod( ... )为每个函数发布标题(仅第一行:),我们可以告诉您特定的问题
nickf 2010年

有关错误消息和PHP编译时间的更多详细信息:bugs.php.net/bug.php?id=46851
hakre 2013年


1
我的问题是参数是带类型提示的,但是后来我没有添加use Closure;到类的顶部(因为类型提示是Closure)。所以...一定要检查您是否缺少像这样的依赖项。
Ryan

Answers:


126

childClass::customMethod()与相比,具有不同的参数或不同的访问级别(公共/私有/受保护)parentClass::customMethod()


1
可能是因为可见性,方法签名在PHP中不是问题
Gabriel Sosa 2010年

43
具有相同的确切参数默认值也很重要。例如,parentClass::customMethod($thing = false)并且childClass::customMethod($thing)会触发错误,因为子方法尚未为第一个参数定义默认值。
查尔斯

1
我认为可见度实际上是一个不同的错误。顺便说一句,在我的商店中,由于这个原因,我们不使用严格模式(我们使用E_ALL,IIRC)。
davidtbernal,2010年

12
在PHP 5.4中,这已更改,顺便说一句:* E_ALL现在在error_reporting配置指令中包括E_STRICT级错误。看到这里:php.net/manual/en/migration54.other.php
Duncan Lock

1
&参数中的“&”号也可能触发此错误。
IvanRF 2014年

36

该消息表示存在某些可能的方法调用,这些方法调用可能在运行时失败。假设你有

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) {;}}

这似乎比需要的限制更多,我认为这是由于内部因素造成的。

可见性差异会导致不同的错误,但出于相同的基本原因。没有任何一种方法比其父方法更不可见。


2
在您的最后一个示例中-这里应该没有错误,因为它是合法的,stdClass $ a比混合$ a更具限制性。有办法解决这个问题吗?我的意思是在这种情况下,PHP应该允许这样做,但仍然会给出错误...
galchen 2012年

2
您的最后一个示例是类型安全的,因此它肯定“比需要的限制更多”。这可能是货物邪教编程的情况下,由于它具有多态性用C ++冲突和Java en.wikipedia.org/wiki/...
Warbo

感谢您的解释,就我而言,您给出的第一个示例正是触发我的错误的原因。
Billynoah

先生,谢谢你。
Eldoïr

22

如果您想保留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();
        // ...

    }
}

我很乐意使用此技巧来解决这些错误。我担心这种方法可能会降低性能吗?我将对此进行研究,但是如果您有任何资源可以帮助回答该问题,那就太好了。
亚当·弗里德曼

取决于我猜的情况。仍然是,它可能有点hacky,但是它是php?已经,有时候可以解决这个问题,谢谢!<@
詹姆斯大师

你救了我的一天!这是在不痛苦的情况下使用php7在服务器上启动旧版php5项目的唯一选择
vladkras

对于这种情况,你可以使用默认值来代替func_get_args(),即Bpublic function foo($a = null, $b = null, $c = null)作为这不撕毁合同的承诺A
杰克

1

只是为了扩展接口上下文中的此错误,如果要像这样键入提示函数参数,则:

接口A

use Bar;

interface A
{
    public function foo(Bar $b);
}

B级

class B implements A
{
    public function foo(Bar $b);
}

如果您忘记use在实现类(B类)上包含该语句,那么即使方法参数相同,您也会收到此错误。


0

在尝试从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();
   }
}

因此,我没有尝试使用“无论如何”的方法,而是编写了一个名为“ getWhatever”的新方法。实际上,他们两个都在做相同的事情,只是返回一个类,但是使用了前面所述的不同名称空间。

希望这可以帮助某人。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.