Эта тема на forum.dklab.ru


Egor Ermakov: Метод родительского класса для данного объекта
Здравствуйте,

Понадобилась следующая вещь: из переопределенного метода потомка, вызвать одноименный метод родительского класса, но для данного объекта (нужен укзатель $this), с параметрами переданными для метода потомка.

Если на примере, то нужно что бы этот код:

class parent{
function doit()
{
echo "<pre>";
echo "doit() from parent:\n";
echo "Dump of \$this variable:\n";
var_dump($this);
echo "Dump of func_get_args():\n";
var_dump(func_get_args());
echo "</pre>";
}
}

class child extends parent{
function doit()
{
$args = func_get_args();

echo "doit() from child:<br />";
echo "dump of func_get_args():<br />";

echo "<pre>";
var_dump($args);
echo "</pre>";

/* А вот что здеь, не ясно */
/* Так передается массив аргументов, а не они сами: */
parent::doit($args);

/* А так, естевтенно, вызвается метод для класса, а не объекта.
То есть $this === NULL */
call_user_func_array(array("parent", "doit"), $args);
}
}
$obj = new child;
$obj->doit();

вывел одинаковый дамп результата func_get_args() и "парвильный" дамп $this.

Собственно как можно это сделать? :)

ps Ах да, желательно сделать это средсвами >= PHP 4.3.0
Юрий Насретдинов:
call_user_func_array(array("parent", "doit"), args);
Нужно указать ссылку на объект, а не его название - типа

call_user_func_array(array(&parent,"doit"),$args);

P.S. если в листинге не опечатка - то не хватает еще знака доллара перед args
Egor Ermakov:
call_user_func_array(array(&parent,"doit"),$args);
Пожалуйста, предлагайте решения, в работоспособности которых вы уверены.

P.S. если в листинге не опечатка
Опечатка, исправлю.

Вопрос остается открытым...
Дмитрий Котеров:
yUAC:
-1
Вообще, если быть откровенным (ты уж извини), глупее постинга и представить сложно. Зачем было его писать, я никак не пойму.

Egor Ermakov:
Вопрос, конечно, интересный. Не факт, что это вообще можно сделать в PHP4 (в PHP5 можно было бы попробовать через отражения).
Egor Ermakov:
Родилось тут одно (почти полное)решение.

Только для того, чтобы оно работало, необходимо что бы родительский класс не звался "parent" (т.к. parent::doit() в php значит не вызвов метода "doit" класса "parent", а вызов метода "doit" родительского класса), честно признаться, я очень зря именно так назвал его в примере выше.

class base{
function doit(&$link)
{
$this->who_changed = "parent";
$link = "set from base class";
echo "<hr>";
echo "<pre>";
echo "doit() from parent:\n";
echo "Dump of \$this variable:\n";
var_dump($this);
echo "Dump of func_get_args():\n";
var_dump(func_get_args());
echo "</pre>";
echo "<hr>";
}
}
class child extends base{
var $who_changed;
function doit(&$link)
{
$this->who_changed = "child";
$link = "set from child class";
echo "doit() from child:<br />";
echo "dump of func_get_args():<br />";
echo "<pre>";
var_dump(func_get_args());
echo "</pre>";

echo "Now calling doit() from parent (named 'base') class:<br />";
echo "\$this->who_changed before call: ".$this->who_changed."<br />";

$code = "base::doit(";
for($i = 0;$i < func_num_args();$i++){
$argname = "arg$i";
$$argname = func_get_arg($i);
$code .= "\$arg$i,";
}
if($i > 0){
$code = substr($code, 0, strlen($code) - 1);
}
$code .= ");";
eval($code);
echo "\$this->who_changed after call: ".$this->who_changed."<br /><br />";
}
}
$string = "set outside";
$obj = new child;
$obj->doit($string, array("key" => "value"), NULL, $obj, 10, "string");
echo "Global \$string: '$string'<br />";

Так вот что интересно, если в eval() пытаться вызвать parent::doit(), то php будет ругаться что мол "parent class not avaible ... in eval()`d code ...", но внутри eval() $this указывает на нужный объект! Это и позволяет вызвать метод родителя таким способом.

Все бы хорошо, но если запустите пример, то увидете что в метод родительского класса первый параметр передался по значению, а не по ссылке. Как это побороть? :-(

ps И что вы думаете о производительности такого решения?
Юрий Насретдинов:
производительности
Тут скорее встает вопрос о целесообразности использования ООП в PHP4.
Дмитрий Котеров:
Ужасное это решение - особенно по производительности.

Попробуйте, что ли, $$argname =& func_get_arg($i). Вдруг сработает...

Кстати, вместо явного указания "base" можно использовать функции PHP для получения базового класса $this (были там такие).
Egor Ermakov:
Тут скорее встает вопрос о целесообразности использования ООП в PHP4.
Ээээ, разве это можно сделать "прямо" в PHP5?
Попробуйте, что ли, $$argname =& func_get_arg($i). Вдруг сработает...
Пробовал, не работает...
Ужасное это решение
Да уж, да еще со ссылками не работает. Вывод -- никакое это не решение)
Кстати, вместо явного указания "base" можно использовать функции PHP для получения базового класса $this (были там такие).
Можно.
Дмитрий Котеров:
Пробовал, не работает...
Может, это потому, что func_get_arg() не может вернуть ссылку? Вроде я где-то в багрепортах читал о таком, и там еще разработчики писали, что в PHP это никогда не будет исправлено.
Egor Ermakov:
Дмитрий Котеров:
Может, это потому, что func_get_arg() не может вернуть ссылку? Вроде я где-то в багрепортах читал о таком, и там еще разработчики писали, что в PHP это никогда не будет исправлено.
На bugs.php.net не нашел информацию о таком баге у func_get_arg()

ps Задал тот же вопрос на xpoint.

Эта тема на forum.dklab.ru