Почему PHP назначает контекст вызову статического метода и не дает уведомления E_STRICT?

Я натолкнулся на очень странное поведение на PHP5.4 (также присутствует в 5.5). В принципе, я вызываю нестатический метод статически, и я не получаю ошибку E_STRICT, где я определенно должен ее получить.

<?php error_reporting(E_ALL); class A { public function iAmNotStatic() {} } 

Теперь, если я это сделаю:

 A::iAmNotStatic(); 

Затем я получаю ошибку, как ожидалось. Strict standards: Non-static method A::iAmNotStatic() should not be called statically .

А также, если я делаю вызов из контекста объекта, я также получаю ту же ошибку (как и ожидалось)

 class B { public function __construct() { A::iAmNotStatic(); } } $b = new B(); // error here, as expected 

Однако, если я это сделаю (назначьте A родителем B):

     class B extends A { public function __construct() { A::iAmNotStatic(); } } $b = new B(); // no error 

    Затем PHP решает, что «нет проблем, у меня есть объект ($ b) с тем же родительским классом (A), давайте просто сделаем его контекстом для iAmNotStatic ».

    Итак, является ли это признаком или ошибкой, и какова может быть цель этого запутанного поведения (недокументированного?)? Благодаря 🙂

    Related of "Почему PHP назначает контекст вызову статического метода и не дает уведомления E_STRICT?"

    В первом случае у вас нет объектного контекста, поскольку вы вызываете свой нестатический метод из внешнего пространства. Но во втором случае у вас есть контекст объекта, поскольку $this будет ссылаться на экземпляр B – и, следовательно, PHP обнаружит, что существует контекст объекта, и, следовательно, это нестатический вызов нестатического метода (все ОК). Если вы сомневаетесь в вызове через :: – тогда, я думаю, вы должны напомнить, что, например, parent::method() является действительным вызовом. Т.е. ссылка здесь не проблема.

    Чтобы быть более конкретным:

     class A { public function foo() { echo('foo called, class: '. get_class($this).PHP_EOL); } } class B extends A { public function __construct() { A::foo(); } } $b=new B(); //foo called, class: B 

    поэтому вы увидите класс B как ожидалось, так как foo() был унаследован.