Иногда мне нужно выполнить метод grandparent (то есть обходить родительский метод), я знаю, что это запах кода, но иногда я не могу изменить другие классы (фреймворки, библиотеки и т. Д.).
В PHP мы можем сделать что-то вроде:
call_user_func(array(get_parent_class(get_parent_class($childObject)), 'grandParentMethod'));
Проблема в том, что если у вас есть ошибки E_STRICT, вы получите сообщение об ошибке:
Строгие стандарты: нестатический метод GrandParent :: grandParentMethod () не следует называть статически …
Я нашел только одно решение для этого (без удаления E_STRICT), и это просто добавление @
для подавления ошибки.
Но это действительно уродливо, знает ли кто-нибудь лучшее решение?
Благодаря ! PS: Я не могу создать новый объект, например:
$grandparent = get_parent_class(get_parent_class($son)); $gp= new $grandparent; $gp->grandParentMethod
потому что мне нужно вызвать мой метод бабушки и дедушки в контексте $ son.
Вы можете использовать ReflectionMethod-> invoke ()
Пример:
<?php class Grandpa { protected $age = 'very old'; public function sayMyAge() { return 'sayMyAge() in Grandpa should be very old. ' . 'My age is: ' . $this->age; } } class Pa extends Grandpa { protected $age = 'less old'; public function sayMyAge() { return 'sayMyAge() in Pa should be less old. ' . 'My age is: ' . $this->age; } } class Son extends Pa { protected $age = 'younger'; public function sayMyAge() { return 'sayMyAge() in Son should be younger. ' . 'My age is: ' . $this->age; } } $son = new Son(); $reflectionMethod = new ReflectionMethod(get_parent_class(get_parent_class($son)), 'sayMyAge'); echo $reflectionMethod->invoke($son); // returns: // sayMyAge() in Grandpa should be very old. My age is: younger
Примечание . Вызываемый метод должен быть общедоступным.
Вы можете вызвать дедушку или бабушку напрямую по имени (без привязки call_user_func
).
class Base { protected function getFoo() { return 'Base'; } } class Child extends Base { protected function getFoo() { return parent::getFoo() . ' Child'; } } class Grandchild extends Child { protected function getFoo() { return Base::getFoo() . ' Grandchild'; } }
Вызов Base::getFoo
может выглядеть как статический вызов (из-за синтаксиса двоеточия), однако это не так. Точно так же, как parent::
не является статическим. Вызов метода из цепочки наследования в классе будет правильно привязывать значение $this
, вызывать его как обычный метод, соблюдать правила видимости (например, защищенные) и не является нарушением какого-либо рода. Сначала это может показаться немного неудобным, но это способ сделать это на PHP.
Вы можете использовать отдельный внутренний метод (например, _doStuff
для дополнения doStuff
) и вызвать его непосредственно у внука через родителя.
// Base class that everything inherits class Grandpa { protected function _doStuff() { // grandpa's logic echo 'grandpa '; } public function doStuff() { $this->_doStuff(); } } class Papa extends Grandpa { public function doStuff() { parent::doStuff(); echo 'papa '; } } class Kiddo extends Papa { public function doStuff() { // Calls _doStuff instead of doStuff parent::_doStuff(); echo 'kiddo'; } } $person = new Grandpa(); $person->doStuff(); echo "\n"; $person = new Papa(); $person->doStuff(); echo "\n"; $person = new Kiddo(); $person->doStuff();
шоу
grandpa grandpa papa grandpa kiddo