在PHP中,从基类的实例创建扩展类的对象

时间:2012-05-22 18:53:52

标签: php

如果我有一个扩展类Bar的类Foo和一个Bar实例,那么无论如何都要使用Bar的实例来“填充”一个新的Foo实例?

基本上,我只能检索Bar,但我想在我的代码中使用Foo,因为它为我提供了许多其他方法。

我看到很多解决方案遇到了类似的问题,但它们似乎都是python或c#。

我无法使用ReflectionClass :: newInstanceArgs,因为我无法访问进入Bar构造函数的数据以便首先创建它。

3 个答案:

答案 0 :(得分:2)

实现此目标的推荐方法是dependency injectionFoo的构造函数可以接受Bar的实例,然后您必须编写代码以从Foo对象加载新Bar对象的状态

如果PHP的功能完全符合您的描述,则会产生问题,因为即使Foo扩展Bar,这两个类仍然可能非常不同。我不知道PHP如何足够聪明,知道如何自动将一个类的实例转换为另一个类的实例。

话虽如此,在正确的情况下,下面的(非常hacky)“解决方案”可以做你所描述的。我不建议实际使用它。我主要是想表明你不得不求助于一些奇怪的事情来做这件事。

function convertObject($object, $newClass)
{
    return unserialize(
        preg_replace(
            '/^O\:\d+\:"[^"]+"/',
            'O:'.strlen($newClass).':"'.$newClass.'"',
            serialize($object)
        )
    );
}

答案 1 :(得分:1)

没有内置方法可以轻松完成您想要的任务。必须重新设计这些类的接口。也许是这样的事情:

<?php
class Bar
{
    ...
}

class Foo extends Bar
{
     public static function fromBar(Bar $bar)
     {
         $foo = new self();
         ... (copy data here) ...

         return $foo;
     }
}

答案 2 :(得分:0)

我刚写了一些这样的例子是为了扩展自定义驱动程序,可能需要额外的支持包用于上述核心驱动程序文件。

// File: parent.php

class parent_class() {

    protected $_protected_object; // set in constructor
    protected $_protected_var = "Something dynamic";

    public function __construct() {
        // keep in mind that if you don't override this constructor, this will execute when extended
    }

    public function create_resource() {
        $this->_protected_object = new SomeObjectInstance();
    }

    public function child_class() {

        static $child = null;

        if (is_null($child)) {

            $file = "child.php";

            if (!\file_exists($file)) {
                throw new Exception("Couldn't load '$file', doesn't exist");
            } else {

                require_once($file);

                $child = new child_class();
                $child->__overload("_protected_object", $this->_protected_object)->__overload("_protected_var", $this->_protected_var);

            }

        }

        return $child;

    }

}

// File: child.php

class child_class extends parent_class {

    protected function __overload($index, &$value) {

        $this->$index =& $value;
        return $this;

    }

    public function __construct() {
        // REMEMBER: if you don't declare this method, the parent's constructor will execute
    }

    public function extended_func() {
        // code
    }

    public function etc() {
        // code
    }

}

// Code instantiating objects:

$parent = new parent_class();
$parent->create_resource();

var_dump($parent);

/**
 *  Would output something like this:
 *  
 *  object(parent_class)#1 (2) {
 *    ["_protected_object":protected]=>
 *    object(SomeObjectInstance)#2 (*) {
 *      %OBJECT PROPERTIES%
 *    }
 *    ["_protected_var":protected]=>
 *    string(17) "Something dynamic"
 *  }
 */

$child = $parent->child_class();

var_dump($child);

/**
 *  Would output something like this:
 *  
 *  object(child_class)#3 (2) {
 *    ["_protected_object":protected]=>
 *    &object(SomeObjectInstance)#2 (*) {
 *      %OBJECT PROPERTIES%
 *    }
 *    ["_protected_var":protected]=>
 *    &string(17) "Something dynamic"
 *  }
 */

请注意,$ child的第二个var_dump()输出与$ parent相同的信息,但您现在可以看到所述属性前面带有&符号(&amp;),表示现在有引用。因此,如果您在父类实例中更改了有关这两个属性的任何内容,它将反映在子类实例中。