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

时间:2010-07-09 00:07:27

标签: php runtime

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

目前我使用classA模仿MRO魔法,但看起来非常不优雅。这需要对classA::__call()的调用者透明地完成,以便外部世界不会意识到classA/B在构建之后已经用classA替换了自己(或其他任何地方)物质)。

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

另外,5.3但理想情况下(yuck)5.2 / x

提前致谢(希望我用Python编写代码)

2 个答案:

答案 0 :(得分:1)

目前在PHP中无法实现......

没有做蠢事。

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

然而,这是非常糟糕的想法。使用__call魔法可能是实现目标最不疯狂的方式。

编辑:始终有runkit,它可以让您执行添加和删除类中方法的操作。但是,它是PECL扩展,甚至可能无法正常工作......

答案 1 :(得分:1)

好的,我对这个问题感兴趣,因为我已经达到了我想要发现PHP的确切限制的程度,包括像这样的小黑客。希望我能在深夜和我身上喝几杯啤酒。由于丑陋的hackishness,我实际上期待被投票。

显然,你不能$this = $that。您也无法将正在尝试创建的全局变量更改为正在构造的对象,并且将尝试这样做将被忽略。正如查尔斯先前所说,这是不可能合理完成的。不是clone,不是serialize()__construct()内没有。

所以,如果你想让$ a首先成为A类的对象,然后将mid-creation转换为B类,尝试这种伪方法是不合理的:你必须连续两次调用A类的__construct。第一次处理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类的另一个方法更重要的是发声,它将全局$ a转换为B类的对象也是一样的,只是因为它看起来不像我的例子那么愚蠢。换句话说,你可能已经像PHP允许的那样做了。

编辑:但实际上,上述仅仅是$a = new A(); $a = new B($a);。为了更好的代码可读性和可维护性,您可能希望不使用我的示例,而是选择实现为您创建和处理这些对象的工厂或处理程序类。我找到了一篇简短而富有洞察力的www.ibm.com文章,解释了工厂如何在PHP中应用它们的概念。从概念上讲,你可能想要一个像cd转换器一样的静态类,这就是Return by Reference - 处理任何范围内对象的变量引用 - 而Variable Objects(参见:midir的评论)该页面) - 动态设置或使用对象 - 派上用场。