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