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

StackOverflow https://stackoverflow.com/questions/16528138

  •  29-05-2022
  •  | 
  •  

The PHP warning, "Strict standards: Declaration of x should be compatible with y" warns you if you write code like:

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

This is sensible, because an object reference like "$a" which you think is an A, may at runtime turn out to be a B, so a dynamically dispatched method call like $a->foo(3) may end up calling B::foo() with the wrong number of arguments.

My question is: why is this same warning applied to static methods, which are not dynamically dispatched?

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

In this example, the function Y::bar() does not override X::bar(), so there is no reason to trigger the warning, but PHP still does. Why?

有帮助吗?

解决方案 2

Unlike Java, you can call static methods on an instance and they are dispatched by the runtime type of that object. So Y::bar() does in fact override X::bar() and it should be compatible.

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

will output (run it here):

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()

(The equivalent code would not compile in Java.)

其他提示

Just like in Java, you can call static methods on an instance too. So there is still room for confusion.

This warning has nothing to do with the real world. Forget the academic examples and look at a real world example. There are 1000's of LOCK manufacturers that make a door lock with a combination touchpad and a key override. Do they use 2 deadbolts - one for the combination lock and one for the key lock? NO. The deadbolt lock is abstracted to the key lock and the combination lock. That's REAL WORLD. PHP ( who will quickly reject any bug reports on this subject) want to stick their heads in the sand on this.

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 is not willing to even discuss this issue. So all my code will contain the following to eliminate this PHP bug:

// 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);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top