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,你会得到这样的印象:他们开始讨厌来自要求更高级功能的其他语言的程序员,迫使他们从本质上成为程序员