Недавно я прочитал о вызове оператора сферы видимости и области видимости (: 🙂 в PHP. Существует два варианта: вызов экземпляра и статический вызов. Рассмотрим следующий список:
<?php class A { public function __call($method, $parameters) { echo "I'm the __call() magic method".PHP_EOL; } public static function __callStatic($method, $parameters) { echo "I'm the __callStatic() magic method".PHP_EOL; } } class B extends A { public function bar() { A::foo(); } } class C { public function bar() { A::foo(); } } A::foo(); (new A)->foo(); B::bar(); (new B)->bar(); C::bar(); (new C)->bar();
Результатом выполнения (PHP 5.4.9-4ubuntu2.2) является:
I'm the __callStatic() magic method I'm the __call() magic method I'm the __callStatic() magic method I'm the __call() magic method I'm the __callStatic() magic method I'm the __callStatic() magic method
Я не понимаю, почему для (new C)->bar();
выполнить __callStatic()
A
? Вызов экземпляра должен выполняться в контексте метода bar (), не так ли? Является ли это особенностью PHP?
Addition1:
Более того, если я не использую магические методы и явно вызываю, все работает так, как ожидалось:
<?php class A { public function foo() { echo "I'm the foo() method of A class".PHP_EOL; echo 'Current class of $this is '.get_class($this).PHP_EOL; echo 'Called class is '.get_called_class().PHP_EOL; } } class B { public function bar() { A::foo(); } } (new B)->bar();
Результат для этого:
I'm the foo() method of A class Current class of $this is B Called class is B
В методе bar()
в C
вас есть A::foo();
:
public function bar() { A::foo(); }
Поскольку этот метод не создает экземпляр A
, а C
не расширяет A
, оператор ::
рассматривается как статический оператор, пытающийся вызвать статический метод A::foo()
. Поскольку foo()
не определен на A
, он возвращается к методу __callStatic()
.
Если вы хотите, чтобы он вызывал нестатический метод без расширения A
, вам нужно создать экземпляр A
:
class C { public function bar() { $aInstance = new A(); $aInstance->foo(); } }
Это связано с тем, что в этом случае у нас нет экземпляра класса A
Заметить, что
class B extends A
Таким образом, new B
дает нам доступ к нестатической версии A->foo
.
Класс C
не расширяет A
поэтому доступны только статические методы A