PHP и Разделение на подклассы Времени выполнения / Объектная реклассификация

Основная установка. У меня есть a classA экземпляр, который является подклассом classX ... На конструкции (или когда-то еще), я хочу, чтобы это загрузило другой класс classB который является также подклассом classX и сама замена classB на месте. Вид подобных фабрика, но та, которая заменяет себя прозрачно. Если потребуется, я могу перенестись classB с classA если существует путь к (во времени выполнения), изменяют подкласс объекта.

В настоящее время я использую classA::__call() эмулировать волшебство MRO, но, кажется очень неэлегантным. Это должно быть сделано прозрачно вызывающей стороне classA/B так, чтобы к внешнему миру, это не знало это classA заменил себя classB после конструкции (или где-либо еще в этом отношении).

Я знаю, что PHP может быть немного тонким при выполнении вещей как это... Я подозреваю, что мы не можем, но это было бы удобно для моей ситуации.

Кроме того, 5.3, но идеально (фу) 5.2/x

Заранее спасибо (пожелание я кодировал в Python),

1
задан Aiden Bell 9 July 2010 в 00:12
поделиться

2 ответа

Хорошо, я заинтересовался этим вопросом, потому что я достиг той точки, где я хотел бы обнаружить точные пределы PHP, включая маленькие хаки вроде этого. Надеюсь, я пойму смысл этого поздно ночью и с несколькими кружками пива. Из-за уродливой хакишности, я ожидаю, что меня не проголосуют.

Очевидно, что вы не можете сделать $this = $that. Вы также не можете изменить глобальную переменную, которую вы в данный момент пытаетесь превратить в объект, пока он строится, и попытка сделать это будет проигнорирована. Как сказал Чарльз ранее, это невозможно сделать разумно. Ни с clone, ни с serialize(), ничего внутри __construct().

Таким образом, если вы хотите, чтобы $a сначала стал объектом класса A, а затем в середине создания был преобразован в класс B, попробуйте использовать этот псевдометод: Вам придется вызывать __construct класса A два раза подряд. Первый раз для создания объекта класса A. Второй раз для завершения создания объекта, преобразуя его в класс B. Класс A обрабатывает первую половину создания, а класс B - вторую:


class A {

    function __construct() {
        $args = func_get_args();  // just to tell us the first round of __construct already occured
        if (array_key_exists(0, $args) AND $args[0]) {
            $GLOBALS['a'] = new B($GLOBALS['a']);
            // stop because "reconstruction" has stopped.  Nothing else you can do to $a in this scope.
            $this->aprop2 = "yay";
            // Seriously, stop.  Don't bother putting more code at this point, you're wasting your time.  Consider $a 'converted and returned' already.
            }
        // build on an object of class a here
        }
    }

class B {

    function __construct($var) {
        // maybe you'd like to do something with old $a?  If so, here's $var for you
        // continue constructing where A left off.
        }

    }


$a = new A(); // object of class A
$a->__construct(true);  // object of class B

Может быть, вместо этого сделать другой метод класса A с более важным названием sounding, который делает то же самое для преобразования глобального $a в объект класса B, просто чтобы он не выглядел так глупо, как мой пример. Другими словами, вы, вероятно, уже делаете это настолько хорошо, насколько позволяет PHP.

Edit: На самом деле, вышеприведенный пример - это не что иное, как $a = new A(); $a = new B($a);. Для лучшей читабельности и сопровождаемости кода, вы можете не использовать мой пример и вместо этого реализовать фабрику или класс-обработчик, который создает и жонглирует этими объектами за вас. Я нашел краткую и содержательную статью www.ibm.com, объясняющую концепцию фабрик, как они применяются в PHP. Возможно, концептуально, вы хотите иметь статический класс, который действует как CD-чейнджер, и вот тут-то и пригодится Return by Reference - для работы с переменной ссылкой на объект в любой области видимости - и Variable Objects (ссылка: комментарии midir на этой странице) - для динамической установки или работы с объектом.

1
ответ дан 2 September 2019 в 23:11
поделиться

В настоящее время это невозможно в PHP ...

Без глупых поступков.

Если каждый экземпляр объекта является ссылкой, и эти ссылки можно найти в $ GLOBALS , и объект знает, как вызывается каждый из этих экземпляров, вы может заменить каждую ссылку на старый объект вашим новым. Внешний мир не заметит разницы.

Однако это впечатляюще ужасная идея. Использование магии __ call , вероятно, является наименее безумным способом достижения цели.

Изменить: всегда есть runkit , который позволяет вам делать такие вещи, как добавление и удаление методов из классов. Однако это расширение PECL и может даже работать некорректно ...

1
ответ дан 2 September 2019 в 23:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: