Основная установка. У меня есть a classA
экземпляр, который является подклассом classX
... На конструкции (или когда-то еще), я хочу, чтобы это загрузило другой класс classB
который является также подклассом classX
и сама замена classB
на месте. Вид подобных фабрика, но та, которая заменяет себя прозрачно. Если потребуется, я могу перенестись classB
с classA
если существует путь к (во времени выполнения), изменяют подкласс объекта.
В настоящее время я использую classA::__call()
эмулировать волшебство MRO, но, кажется очень неэлегантным. Это должно быть сделано прозрачно вызывающей стороне classA/B
так, чтобы к внешнему миру, это не знало это classA
заменил себя classB
после конструкции (или где-либо еще в этом отношении).
Я знаю, что PHP может быть немного тонким при выполнении вещей как это... Я подозреваю, что мы не можем, но это было бы удобно для моей ситуации.
Кроме того, 5.3, но идеально (фу) 5.2/x
Заранее спасибо (пожелание я кодировал в Python),
Хорошо, я заинтересовался этим вопросом, потому что я достиг той точки, где я хотел бы обнаружить точные пределы 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 на этой странице) - для динамической установки или работы с объектом.
В настоящее время это невозможно в PHP ...
Без глупых поступков.
Если каждый экземпляр объекта является ссылкой, и эти ссылки можно найти в $ GLOBALS
, и объект знает, как вызывается каждый из этих экземпляров, вы может заменить каждую ссылку на старый объект вашим новым. Внешний мир не заметит разницы.
Однако это впечатляюще ужасная идея. Использование магии __ call
, вероятно, является наименее безумным способом достижения цели.
Изменить: всегда есть runkit , который позволяет вам делать такие вещи, как добавление и удаление методов из классов. Однако это расширение PECL и может даже работать некорректно ...