Jugué un poco con todo. Parece que lo único que puede hacer con ReflectionClass
es reemplazar un método existente. Pero incluso eso sería indirectamente.
En realidad, no conozco ningún lenguaje basado en clases, donde existen clases dinámicas (de nuevo, mi conocimiento es bastante limitado). Lo he visto hecho solo en lenguajes basados en prototipos (javascript, ruby, smalltalk). En cambio, lo que puede hacer, en PHP 5.4, es usar Closure
y agregar nuevos métodos a un objeto existente .
Aquí es una clase que permitirá realizar tales perversión a cualquier objeto:
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
);
}
}
}
Para usar esto, usted tiene que proporcionar constructor con un objeto existente. Aquí es pequeño ejemplo de uso:
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'
No es exactamente lo que quiere, pero que yo sepa esto es lo más cerca que puede llegar.
Impresionante. Me encantan estas nuevas características PHP – Thomas
¿Cuál es el punto del método __call aquí, si \ Closure :: bind hace lo mismo, y viceversa? – jayarjo
@jayarjo '\ Closure :: bind' cambia el contexto de la función anónima (en este caso, se asegura de que, dentro del cierre,' $ this' se refiere al objeto correcto). Sin embargo, no hace que esa función sea un método de '$ this'. Todavía necesitamos '__call' para permitir que el código externo llame al cierre como si fuera un método. –