PHP:为什么是"严格的标准:x的声明应该与y兼容;应用于静态方法


PHP: why is "Strict standards: Declaration of x should be compatible with y" applied to static methods?

PHP警告,"严格标准:x的声明应该与y兼容"警告您,如果您编写如下代码:

class A {
  function foo($x) {
    ..
  }
}
class B extends A {
  function foo() {
    ..
  }
}

这是合理的,因为像"$a"这样的对象引用,你认为是A,可能在运行时结果是B,所以像$a->foo(3)这样动态分配的方法调用可能最终调用B::foo()的参数数量错误。

我的问题是:为什么这个相同的警告应用到静态方法,这不是动态调度?

class X {
  static function bar($x) {
    ..
  }
}
class Y extends X {
  static function bar() {
    ..
  }
}

在这个例子中,函数Y::bar()没有覆盖X::bar(),所以没有理由触发警告,但是PHP仍然会触发警告。为什么?

就像在Java中一样,您也可以在实例上调用静态方法。所以还是有混淆的余地。

与Java不同,您可以在实例上调用静态方法,并且它们由该对象的运行时类型分配。所以Y::bar()实际上覆盖了X::bar(),它应该是兼容的。

<?php
class X {
  static function bar($x) {
    echo "X::bar() with x = $x'n";
  }
}
class Y extends X {
  static function bar() {
    echo "Y::bar()'n";
  }
}
echo "Static dispatch:'n";
X::bar(1);
Y::bar();
echo "Dynamic dispatch of a static method (surprise!):'n";
$arr = array(new X(), new Y());
foreach ($arr as $a) {
  $a::bar(1);
}

将输出(在这里运行):

Warning: Declaration of Y::bar() should be compatible with X::bar($x) in /in/phAWB on line 12
Static dispatch:
X::bar() with x = 1
Y::bar()
Dynamic dispatch of a static method (surprise!):
X::bar() with x = 1
Y::bar()

(等效代码在Java中无法编译)

这个警告与现实世界无关。忘记学术上的例子,看看现实世界的例子。有成千上万的锁制造商生产带有触摸板和钥匙覆盖组合的门锁。他们是否使用两个门栓——一个用于密码锁,一个用于钥匙锁?不。将门栓锁抽象为钥匙锁和密码锁。这就是现实世界。PHP(他们会很快拒绝任何关于这个主题的错误报告)想把他们的头埋在沙子里。

class abstractLock
{
    private $locked = true;
    public function unlock()
    {
       $this->locked=false;
    }
    public function lockStatus()
    {
        if($this->locked) return "Locked'n";
        else return "Unlocked'n";
    }
}
class combinationLock extends abstractLock
{
    private $combination = '32-10-21'; // combination
    public function unlock($combination)        // unlock WITH combination
    {
        if($this->combination == $combination) parent::unlock();
    }
}
class paddleLock extends abstractLock
{
    private $key = '100,70,80,30,50,90,60,40,100'; // ridge heights
    public function unlock($key)                            // unlock WITH key
    {
        if($this->key == $key) parent::unlock();
    }
} 
$lock1 = new paddleLock();
echo "paddleLock is " . $lock1->lockStatus();
$lock1->unlock('100,70,80,30,50,90,60,40,100');
echo "paddleLock is " . $lock1->lockStatus();
$lock2 = new combinationLock();
echo "combinationLock is " . $lock2->lockStatus();
$lock2->unlock('32-10-21');
echo "combinationLock is " . $lock2->lockStatus();

PHP甚至不愿意讨论这个问题。因此,我的所有代码将包含以下内容以消除PHP 错误:

// FIX PHP's bogus warning of: PHP Warning: Declaration of * should be compatible with
if (PHP_MAJOR_VERSION >= 7) {
    set_error_handler(function ($errno, $errstr) {
       return strpos($errstr, 'Declaration of') === 0;
    }, E_WARNING);
}