基本设置。我有一个 classA
实例,它是 classX
的子类...在构造时(或其他时候),我希望它加载另一个类 classB
> 它也是 classX
的子类,并就地用 classB
替换它自己。有点像工厂,但可以透明地自我更换。如果需要,如果有办法(在运行时)更改对象的子类,我可以用 classA
包装 classB
。
目前我正在使用 classA::__call() 来模拟 MRO 魔法,但这看起来非常不优雅。这需要对 classA/B
的调用者透明地完成,以便外界不知道 classA
已将其自身替换为 classB< /code> 构建后(或其他任何地方)。
我知道 PHP 在做这样的事情时可能会有点薄……我怀疑我们不能,但这对我的情况来说会很方便。
另外,5.3,但理想情况下(恶心)5.2/x
提前致谢(希望我用 Python 编码)
Basic setup. I have a classA
instance which is a subclass of classX
... On construction (or sometime else), I want it to load another class classB
which is also a subclass of classX
and replace itself with classB
in situ. Sort of like a factory, but one that replaces itself transparently. If need be, I can wrap classB
with classA
if there is a way to (at runtime) change the subclass of an object.
Currently I am using classA::__call()
to emulate MRO magic, but is seems very inelegant. This needs to be done transparently to the caller of classA/B
so that to the outside world, it isn't aware that classA
has replaced itself with classB
after construction (or anywhere else for that matter).
I know PHP can be a bit thin when doing things like this ... I am suspecting we can't, but it would be handy for my situation.
Also, 5.3 but ideally (yuck) 5.2/x
Thanks in advance (wishing I was coding in Python)
发布评论
评论(2)
好吧,我对这个问题很感兴趣,因为我已经达到了想要发现 PHP 的确切限制的地步,包括像这样的小技巧。希望我能在深夜喝点啤酒明白道理。由于丑陋的黑客行为,我实际上预计会被否决。
显然,你不能这样做
$this = $that
。您也无法在构造对象时更改当前尝试将其放入对象的全局变量,并且尝试这样做将被忽略。正如查尔斯之前所说,这是不合理的做法。不使用clone
,不使用serialize()
,也不使用__construct()
。因此,如果您希望 $a 首先成为 A 类的对象,然后在创建过程中转换为 B 类,请尝试以下伪方法:您必须连续调用 A 类的 __construct 两次,这是不合理的。第一次处理A类的构造。第二次完成将其转换为B类的对象。A类处理构造的前半部分,B类处理后半部分:
也许可以改为使A类的另一个方法命名为更重要的听起来,它执行相同的操作将全局 $a 转换为 B 类的对象,只是这样它看起来不像我的示例那么愚蠢。换句话说,您可能已经在 PHP 允许的范围内做到了最好。
编辑:实际上,上面的内容只不过是
$a = new A(); $a = new B($a);
。为了获得更好的代码可读性和可维护性,您可能不想使用我的示例,而是选择实现一个工厂或处理程序类来为您创建和处理这些对象。我发现了一个简短而富有洞察力的 www.ibm.com文章解释了工厂的概念如何在 PHP 中应用。也许从概念上讲,您想要一个像 CD 换片器一样的静态类,这就是 通过引用返回 - 在任何范围内使用对对象的变量引用 - 和 变量对象(参考:midir 在该页面上的评论) - 动态设置或使用对象 - 派上用场。Ok, I've taken an interest in this question because I've reached the point where I'd like to discover the exact limits of PHP, including little hacks like this. Hopefully, I'll make sense this late at night and a few beers in me. Because of the ugly hackishness, I'm actually expecting to be downvoted.
Obviously, you can't do
$this = $that
. You also can't change the global variable you're currently trying to make into an object while it's being constructed, and attempting to do so will be ignored. As Charles said earlier, this can't be reasonably done. Not withclone
, notserialize()
, nothing within__construct()
.So, unreasonably if you want $a to first become an object of class A, then convert mid-creation to class B, try this pseudo method: You'll have to call __construct of class A twice in a row. First time to handle construction of class A. Second time to complete the object converting it to class B. Class A handles the first half of construction, and class B the second half:
Maybe instead make another method of class A named more importantly sounding, which does the same thing to convert the global $a into object of class B, just so it doesn't look so stupid as my example. In other words, you're probably already doing it as best as PHP allows.
Edit: Really though, the above is nothing more than
$a = new A(); $a = new B($a);
. For better code readability and maintainability, you may want not to use my example and instead opt to implement a factory or handler class that creates and juggles these objects for you. I found a brief and insightful www.ibm.com article explaining the concept of factories how they are applied in PHP. Maybe conceptually, you want a static class that acts like a cd changer, and this is where Return by Reference - to work with a variable reference to the object in any scope - and Variable Objects (ref: midir's comments on that page) - to dynamically set or work with the object - comes in handy.目前这在 PHP 中是不可能的......
不做愚蠢的事情。
如果对象的每个实例都是引用,并且这些引用可以在
$GLOBALS
中找到,并且该对象知道这些实例中的每一个被调用,那么您 >可以用新对象替换旧对象的每个引用。外界不会知道其中的区别。然而,这是一个极其糟糕的想法。使用 __call 魔法可能是实现目标的最不疯狂的方法。
编辑:总是有 runkit,它可以让你做诸如添加之类的事情并从类中删除方法。然而,它是一个 PECL 扩展,甚至可能无法正常工作......
This is not currently possible in PHP...
Without doing stupid things.
If every instance of the object is a reference, and those references can be found in
$GLOBALS
, and the object knows what every one of those instances is called, you could replace each and every reference of the old object with your new object. The outside world won't know the difference.This is, however, a spectacularly awful idea. Using
__call
magic is probably the least insane way of accomplishing your goal.Edit: There's always runkit, which will let you do things like add and remove methods from classes. However, it's a PECL extension and might not even work correctly...