Немного поиграл со всей штукой. Кажется, что только то, что вы можете потенциально сделать с ReflectionClass
, заключается в замене существующего метода. Но даже это было бы косвенно.
На самом деле я не знаю ни одного языка на основе класса, где существуют динамические классы (опять же, мои знания весьма ограничены). Я видел это только в языках, основанных на прототипах (javascript, ruby, smalltalk). Вместо этого вы можете сделать в PHP 5.4, использовать Closure
и добавить новые методы в существующий объект .
Вот класс, который позволит вам выполнять такие извращения для любого объекта:
class Container
{
protected $target;
protected $className;
protected $methods = [];
public function __construct($target)
{
$this->target = $target;
}
public function attach($name, $method)
{
if (!$this->className)
{
$this->className = get_class($this->target);
}
$binded = Closure::bind($method, $this->target, $this->className);
$this->methods[$name] = $binded;
}
public function __call($name, $arguments)
{
if (array_key_exists($name, $this->methods))
{
return call_user_func_array($this->methods[$name] , $arguments);
}
if (method_exists($this->target, $name))
{
return call_user_func_array(
array($this->target, $name),
$arguments
);
}
}
}
Чтобы использовать эту функцию, вы должны предоставить конструктор с существующим объектом. Вот небольшой пример использования:
class Foo
{
private $bar = 'payload';
};
$foobar = new Foo;
// you initial object
$instance = new Container($foobar);
$func = function ($param)
{
return 'Get ' . $this->bar . ' and ' . $param;
};
$instance->attach('test', $func);
// setting up the whole thing
echo $instance->test('lorem ipsum');
// 'Get payload and lorem ipsum'
Не совсем то, что вы хотите, но AFAIK это как близко вы можете получить.
Awesome. Любить эти новые функции PHP. – Thomas
. В чем смысл метода __call здесь, если \ Closure :: bind делает вещь, и наоборот? – jayarjo
@jayarjo '\ Closure :: bind' изменяет контекст анонимной функции (в этом случае он гарантирует, что в пределах замыкания' $ this' ссылается на правильный объект). Однако это не делает эту функцию в методе '$ this'. Нам все еще нужно '__call', чтобы позволить внешнему коду вызывать закрытие, как если бы это был метод. –