Переопределение функций класса PHP на лету?
Я пытаюсь выяснить, как импортировать большое количество функций класса PHP на лету. Например...
class Entity
{
public function __construct($type)
{
require_once $type."_functions.php"
}
// ...
}
$person = new Entity("human");
$person->sayhi();
$cow = new Entity("cow");
$cow->sayhi();
human_functions.на PHP:
class Entity redefines Entity
{
public function sayhi()
{
echo "Hello world!";
}
}
cow_functions.на PHP:
class Entity redefines Entity
{
public function sayhi()
{
echo "Moo!";
}
}
я нашел несколько вариантов как classkit_method_redefine()
и runkit_method_redefine()
(которые являются" экспериментальными", и они не могут изменить текущий класс в любом случае). Я сейчас на PHP 5.3.3, поэтому я не могу использовать черт (не уверен, если это то, что я ищу в любом случае). Я!--21-->есть удалось переопределить переменную обработчика следующим образом:
// Example 2:
class OtherEntity { /* Code Here */ }
class Entity
{
public function __construct($type)
{
global $foo;
unset($foo);
$foo = new OtherEntity();
}
}
$foo = new Entity();
но это выглядит как очень способ суховато. Что еще более важно, если я не назову экземпляр класса $foo
, тогда это не сработает. Есть ли обходные пути для того, что я пытаюсь сделать?
Примечание: я знаю, что могу расширить класс, но в моем случае, когда класс сущности инициируется, нет безопасного способа заранее узнать, с каким подклассом он должен быть инициирован. Возможно, есть способ, который я мог бы написать, например:
public function changeClass
{
this->class = OtherEntity;
}
Спасибо за вашу помощь!
2 ответов
вот идея возможного решения, которое вы могли бы попробовать. Пусть Cow
и Human
классы расширяют Entity
класса. Однако Entity
класс будет использовать завод для создания экземпляра объектов на основе безопасного значения. Давайте рассмотрим это более подробно:
/*
* Class Entity should not be able to be instantiated.
* It should contain a factory to instantiate the
* appropriate entity and an abstract function declaring
* the method that each entity will need to implement.
*/
abstract class Entity {
public static function factory($type) {
return (is_subclass_of($type, "Entity")) ? new $type() : FALSE;
}
abstract public function sayHi();
}
/*
* Human class extends Entity and implements the
* abstract method from Entity.
*/
class Human extends Entity {
public function sayHi() {
echo "Hello World!";
}
}
/*
* Cow class extends Entity and implements the
* abstract method from Entity.
*/
class Cow extends Entity {
public function sayHi() {
echo "Moo!";
}
}
теперь, чтобы использовать этот метод, вызовите метод factory, и если все работает хорошо, он создаст экземпляр надлежащего класса, который расширит Entity
.
$person = Entity::factory("Human");
$person->sayHi();
$cow = Entity::factory("Cow");
$cow->sayHi();
используя is_subclass_of()
будет держать вас в безопасности, потому что если переданное значение не класс, расширяющий Entity
, вам будет возвращено значение FALSE
.
если вы хотите увидеть приведенный выше код в действии, скопируйте приведенный выше php-код и протестируйте его наphpfiddle.org.
одна вещь вы можете сделать, это создать Human
и Cow
как подклассы Entity
. Когда вы делаете new Entity("Human")
, вы можете сохранить недавно созданный Human
объект внутри the Entity
экземпляра.
затем вы можете использовать __call
для перенаправления вызовов метода "дочерний элемент".
class Entity{
private $child;
public function __construct($type){
$this->child = new $type;
}
public function __call($func, $params=array()){
$method = method_exists($this, $func)
? [$this, $func] : [$this->child, $func];
return call_user_func_array($method, $params);
}
}
class Human extends Entity{
public function __construct(){}
public function sayhi(){
echo "Hello world!";
}
}
class Cow extends Entity{
public function __construct(){}
public function sayhi(){
echo "Moo!";
}
}
$person = new Entity("Human");
$person->sayhi();
$cow = new Entity("Cow");
$cow->sayhi();
единственным недостатком является то, что $person
и $cow
как Entity
объекты.