开发者

Copying an instance of a PHP class while preserving the data in a base class?

I have the following three classes:

class a
{ public $test; }

class b extends a { }
class c extends a
{
    function return_instance_of_b() { }
}

As you can see, both classes b and c derive from a. In the return_instance_of_b() 开发者_运维百科function in c, I want to return an instance of the class b. Basically return new b(); with one additional restriction:

I need the data from the base class (a) to be copied into the instance of b that is returned. How would I go about doing that? Perhaps some variant of the clone keyword?


You can use the get_class_vars function to retrieve the names of the variables you want to copy, and just loop to copy them.

The variables that are defined are protected so they are visible to get_class_vars in its scope (since c extends a), but not directly accessible outside the class. You can change them to public, but private will hide those variables from get_class_vars.

<?php
class a
{ 
    protected $var1;
    protected $var2;
}

class b extends a 
{
}

class c extends a
{
    function __construct()
    {
        $this->var1 = "Test";
        $this->var2 = "Data";
    }

    function return_instance_of_b() 
    {
        $b = new b();
        // Note: get_class_vars is scope-dependant - It will not return variables not visible in the current scope
        foreach( get_class_vars( 'a') as $name => $value) {
            $b->$name = $this->$name;
        }
        return $b;
    }
}

$c = new c();
$b = $c->return_instance_of_b();
var_dump( $b); // $b->var1 = "Test", $b->var2 = "Data


I believe you can achieve this with some reflection. Not very pretty code, I'm sure there is a much more succinct method to achieve this but here you go.

class a
{ 
    public $foo;
    public $bar;

    function set($key, $value) {
        $this->$key = $value;
    }

    function get($key) {
        return $this->$key;
    }
}

class b extends a 
{ 
    function hello() {
        printf('%s | %s', $this->foo, $this->bar);
    }
}
class c extends a
{   
    public $ignored;

    function return_instance_of_b() {
    $b = new b();
    $reflection = new ReflectionClass($this);
    $parent = $reflection->getParentClass();
    foreach($parent->getProperties() as $property) {
        $key = $property->getName();
        $value = $property->getValue($this);
        $b->$key = $value;
    }

    return $b;
    }
}

$c = new c();
$c->set('foo', 'bar');
$c->set('bar', 'bar2');
$c->set('ignored', 'should be!');

$b = $c->return_instance_of_b();
$b->hello();
// outputs bar | bar2

Additionally you could use nickb's answer but instead of hard coding the class you could use get_parent_class

function return_instance_of_b() 
    {
        $b = new b();
        foreach(get_class_vars(get_parent_class(__CLASS__)) as $name => $value) {
            $b->$name = $this->$name;
        }
        return $b;
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜