5

クラス Bar を拡張するクラス Foo と Bar のインスタンスがある場合、その Bar のインスタンスを使用して Foo の新しいインスタンスを「生成」する方法はありますか?

基本的に、私は Bar しか取得できませんが、多くの追加メソッドが得られるので、コードで Foo を使用したいと考えています。

同様の質問にかなりの数の解決策が出てくるのを見ましたが、それらはすべて python または c# のようでした。

そもそも Bar を作成するために Bar のコンストラクターに入ったデータにアクセスできないため、ReflectionClass::newInstanceArgs を使用できません。

4

3 に答える 3

2

これを実現するための推奨される方法は、依存性注入を使用することです。のコンストラクターはFooのインスタンスを受け入れることができ、その場合、オブジェクトからBar新しいオブジェクトの状態をロードするコードを記述する必要があります。FooBar

PHPにあなたが説明したとおりの機能がある場合、それは問題になります。Foo拡張したとしてもBar、2つのクラスは非常に異なる可能性があるからです。PHPが、あるクラスのインスタンスを別のクラスのインスタンスに自動的に変換する方法を知るのに十分なほど賢い方法がわかりません。

そうは言っても、正しい状況下では、以下の(非常にハッキーな)「解決策」があなたの説明どおりに機能する可能性があります。実際に使用することはお勧めしません。私は主に、これを行うためにいくつかの奇妙なものに頼らなければならないことを示したかっただけです。

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 の 2 番目の var_dump() は $parent と同じ情報を出力することに注意してください。ただし、プロパティの前にアンパサンド (&) が付いていることがわかります。したがって、これら 2 つのプロパティに関して親クラスのインスタンスで何かを変更すると、子クラスのインスタンスに反映されます。

于 2015-04-15T19:28:47.663 に答える