PHP和运行时子类化/对象重新分类

PHP和运行时子类化/对象重新分类,php,runtime,Php,Runtime,基本设置。我有一个classA实例,它是classX的一个子类。。。在构造时(或其他时候),我希望它加载另一个类classB,它也是classX的子类,并在原地用classB替换自己。有点像一个工厂,但它可以透明地替换自己。如果需要,我可以使用classA包装classB,如果有方法(在运行时)更改对象的子类 目前我正在使用classA::u call()来模拟MRO魔术,但它似乎非常不雅观。这需要对classA/B的调用方透明地进行,以便对外部世界来说,它不会意识到classA在构建后(或在其

基本设置。我有一个
classA
实例,它是
classX
的一个子类。。。在构造时(或其他时候),我希望它加载另一个类
classB
,它也是
classX
的子类,并在原地用
classB
替换自己。有点像一个工厂,但它可以透明地替换自己。如果需要,我可以使用
classA
包装
classB
,如果有方法(在运行时)更改对象的子类

目前我正在使用
classA::u call()
来模拟MRO魔术,但它似乎非常不雅观。这需要对
classA/B
的调用方透明地进行,以便对外部世界来说,它不会意识到
classA
在构建后(或在其他任何地方)已被
classB
取代

我知道PHP在做这样的事情时可能有点瘦。。。我怀疑我们不能,但这对我的情况来说很方便

另外,5.3,但理想情况下(恶心)为5.2/x


提前感谢(希望我是用Python编写的)

这在PHP中是不可能的

不做傻事

如果对象的每个实例都是引用,并且这些引用可以在
$GLOBALS
中找到,并且对象知道这些实例中的每个实例都被调用了什么,那么可以用新对象替换旧对象的每个引用。外界不会知道其中的区别

然而,这是一个极其可怕的想法。使用
\u call
魔术可能是实现目标最不疯狂的方式


编辑:总是有,这将允许您从类中添加和删除方法。但是,它是一个PECL扩展,甚至可能无法正常工作…

好吧,我对这个问题很感兴趣,因为我已经到了想发现PHP的确切限制的地步,包括像这样的小技巧。希望我能在深夜和喝几杯啤酒的时候明白这一点。因为丑陋的黑客行为,我真的希望被否决

显然,您不能执行
$this=$that
。在构造对象时,您也不能将当前试图生成的全局变量更改为对象,并且尝试这样做将被忽略。正如查尔斯早些时候所说,这是不合理的。不使用
克隆
,不使用
序列化()

因此,如果您不合理地希望$a首先成为类a的对象,然后将中间创建转换为类B,请尝试这种伪方法:您必须连续调用类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 甲级{ 函数_u构造(){ $args=func_get_args();//告诉我们第一轮的u构造已经发生了 如果(数组\键\存在(0,$args)和$args[0]){ $GLOBALS['a']=新的B($GLOBALS['a']); //停止,因为“重建”已停止。在此范围内,您无法对$a执行任何其他操作。 $this->aprop2=“耶”; /认真地,停下来。不要在这一点上加更多的代码,你在浪费时间。 } //在这里构建一个a类对象 } } B类{ 函数构造($var){ //也许你想用旧的$a做点什么?如果是的话,这里有$var给你 //在一个中断的地方继续构建。 } } $a=新的a();//A类物品 $a->uu构造(真);//B类对象 也许可以改为创建另一个名为“更重要的声音”的类A方法,它做同样的事情将全局$A转换为类B的对象,只是为了让它看起来不像我的示例那样愚蠢。换句话说,您可能已经尽了PHP所能做到最好了


编辑:实际上,上面的内容只不过是
$a=newa()$a=新的B($a)。为了更好的代码可读性和可维护性,您可能不想使用我的示例,而是选择实现一个工厂或处理程序类来为您创建和处理这些对象。我发现了一篇简短而深刻的文章,解释了工厂的概念,以及如何在PHP中应用工厂。从概念上讲,您可能需要一个像cd换碟机一样工作的静态类,这就是在任何范围内使用对象的变量引用的地方,以及(参考:该页面上的midir注释)-动态设置或使用对象-非常方便。

因此,基本上您正在寻找php中与
obj相当的对象。
。我不禁想知道,为什么您会想做这样的事情=)有趣的是,php在
$this=$that
上抱怨和崩溃,却完全忽略了
unset($this)
。我想知道在引擎开始注意到之前,有多少个
unset($this)
可以放入一个类中。@VolkerK-是的,@Jani Hartikainen-模块加载系统的改装+1,感谢您的输入。我不想过多地抛弃PHP,但它是次优的:PIndeed,PHP不能很好地完成元编程等有趣和高级的事情。此外,我还用另一个选项更新了我的答案。@Charles--Runkit看起来真脏。感叹,谢谢:)@Aiden我得到的印象是PHP开发团队希望保持这种方式,而且有很好的理由。您主要使用PHP编写HTML输出脚本,而不是设计卫星。PHP每年都在增长,以适应更多的细分市场,如OOP、CLI、内存、图形等,最终是.NET。浏览他们的bug数据库和RFC,你会得到这样的印象:他们开始讨厌来自要求更高级功能的其他语言的程序员,迫使他们从本质上成为程序员