5

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

本质上,我只能检索 Bar,但我想在我的代码中使用 Foo,因为它给了我很多额外的方法。

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

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

4

3 回答 3

2

推荐的方法是通过依赖注入。您的构造函数 forFoo可以接受 的实例Bar,然后您必须编写代码以Foo从对象加载新对象的状态Bar

如果 PHP 具有完全符合您描述的功能,那将是有问题的,因为即使Fooextends Bar,这两个类仍然可能非常不同。我不明白 PHP 是如何聪明到知道如何自动将一个类的实例转换为另一个类的实例。

话虽如此,在正确的情况下,下面的(非常hacky)“解决方案”可以做你描述的事情。我不建议实际使用它。我主要只是想表明你必须诉诸一些奇怪的东西才能做到这一点。

function convertObject($object, $newClass)
{
    return unserialize(
        preg_replace(
            '/^O\:\d+\:"[^"]+"/',
            'O:'.strlen($newClass).':"'.$newClass.'"',
            serialize($object)
        )
    );
}
于 2012-05-22T19:21:42.060 回答
1

没有内置的方法可以轻松地做你想做的事。这些类的接口必须重新设计一点。也许是这样的:

<?php
class Bar
{
    ...
}

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

         return $foo;
     }
}

于 2012-05-22T20:18:44.893 回答
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 相同的信息,只是您现在可以看到所述属性前面带有与号 (&),表示现在有引用。因此,如果您更改父类实例中关于这两个属性的任何内容,它将反映在子类实例中。

于 2015-04-15T19:28:47.663 回答