【问题标题】:Declaration of Methods should be Compatible with Parent Methods in PHP方法声明应与 PHP 中的父方法兼容
【发布时间】:2011-03-08 02:54:47
【问题描述】:
严格标准:childClass::customMethod() 的声明应该与 parentClass::customMethod() 的声明兼容

PHP 中出现此错误的可能原因是什么?我在哪里可以找到关于兼容意味着什么的信息?

【问题讨论】:

  • notJim 完全正确。 @waiwai933,如果您可以发布每个函数的标题(仅第一行:function customMethod( ... )),我们可以告诉您具体问题
  • 有关错误消息和 PHP 编译时间影响的更多详细信息:bugs.php.net/bug.php?id=46851
  • 我的问题是一个参数是类型提示的,但是我没有在我的类的顶部添加use Closure;(因为类型提示是Closure)。所以...一定要检查你是否缺少这样的依赖项。

标签: php methods standards-compliance


【解决方案1】:

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

【讨论】:

  • 可能是因为 visibility,方法签名在 PHP 中不是问题
  • 具有完全相同的参数默认值也很重要。例如,parentClass::customMethod($thing = false)childClass::customMethod($thing) 会触发错误,因为子方法没有为第一个参数定义默认值。
  • 我相信可见性实际上是一个不同的错误。顺便说一句,在我的商店我们不使用严格模式,因为这个(我们使用 E_ALL,IIRC)。
  • 这在 PHP 5.4 中有所改变,顺便说一句:* E_ALL 现在在 error_reporting 配置指令中包含 E_STRICT 级别的错误。见这里:php.net/manual/en/migration54.other.php
  • 参数中缺少与号 (&) 也会触发此错误。
【解决方案2】:

此消息意味着某些可能的方法调用在运行时可能会失败。假设你有

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

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

可见性差异会导致不同的错误,但基本原因相同。没有任何方法比它的父方法更显眼。

【讨论】:

  • 在你的最后一个例子中 - 这里不应该有错误,因为它是合法的,stdClass $a 比混合 $a 更具限制性。有没有办法解决这个问题?我的意思是在这种情况下 PHP 应该允许这样做,但它仍然给出错误...
  • 你的最后一个例子是类型安全的,所以它肯定是“比它需要的限制更多”。这可能是货物崇拜编程的一个案例,因为它与 C++ 和 Java 中的多态性冲突en.wikipedia.org/wiki/…
  • 感谢您的解释,在我的情况下,您给出的第一个示例正是引发我错误的原因。
  • 谢谢你,先生。
【解决方案3】:

如果您想在不关闭任何错误的情况下保持 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 项目的唯一选择
  • 对于这种情况,您可以使用默认值代替func_get_args(),即Bpublic function foo($a = null, $b = null, $c = null),因为这不会违反A所承诺的合同。
【解决方案4】:

只是为了在接口的上下文中扩展此错误,如果您正在键入提示您的函数参数,如下所示:

接口 A

use Bar;

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

B类

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

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

【讨论】:

    【解决方案5】:

    我在尝试从 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”的新方法。事实上,它们都在做同样的事情,只是返回一个类,但使用了不同的命名空间,正如我之前描述的那样。

    希望这可以帮助某人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 2016-06-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多