Переопределение функций класса 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 объекты.