On Wed, Sep 22, 2010 at 5:35 AM, Daniel Kolbo <kolb0057@xxxxxxx> wrote: > Hello PHPers, > > I have: > > class A { > ...code > } > > class B extends A { > ...code > } > > $a = new A(); > > $b = new B(); > > I would like to get all of the properties of $a into $b by value. first off you have to be careful here since there is no real explicit copy by value in php since internally the engine uses copy on write. there is a caveat in __clone however, where you can force new instances of objects to be created in cloned instance variables rather than a reference to the original object in member variables of the cloned instance. > Class > A extends 3 other classes. I would like a way to not have to manage a > 'copy' method in B if A or one of the subclasses of A change. > well since B extends A directly here, obviously theres no need to worry about other subclasses of A changing when considering the copy constructor (__clone in php) of B. anyway if A changes you need only potentially revise the __clone() implementation of A. > I was reading about clone, but this doesn't really seem to help me in > this situation. > egh? define __clone() in A to be responsible for any member variables defined in A then define __clone() in B to be responsible for any additional member variables defined therein, making sure to invoke parent::__clone() from B. naturally if you add or remove member variables from A you revise the __clone() implementation of A, the same is true for B. this isnt a maintenance nightmare and is also a sound oop practice. the same idea would be applied to a copy constructor in java or c++. note also that php internally manages a shallow copy out of the box, meaning you wont have to implement any code to 'copy' non-object member variables in cloned objects. you will however have to determine if a reference to the same objects in instance variables of cloned objects is appropriate or if each instance of the class you are cloning needs to have their own instance of member variables referencing objects. here is a somewhat contrived example which illustrates everything. all you have to do is run the script and inspect the id of each object stored in member variables. what youll find is that in each instance of B shallowObj is referring to the same instance of stdClass, yet anotherObj from B and someObj from A are each explicitly 'copied' for each instance of B. also youll notice that A manages cloning of someObj and B manages cloning of anotherObj, keeping in line with encapsulation. also notice the scalar variables are 'copied' by the engine w/ no work in userspace. <?php class A { public $blah = 0; protected $meh = 1; private $care = 2; private $someObj = null; public function __construct() { $this->someObj = new stdClass(); } public function __clone() { // note only if we want to force a new instance of // stdClass into $this->someObj in cloned instance of A $this->someObj = clone $this->someObj; } } class B extends A { protected $what = 5; protected $anotherObj = null; protected $shallowObj = null; public function __construct() { parent::__construct(); $this->anotherObj = new stdClass(); $this->shallowObj = new stdClass(); } public function __clone() { // make sure to invoke parent __clone() parent::__clone(); // note as in A::__clone() above, forcing new instance // of $this->anotherObj in cloned instance of B $this->anotherObj = clone $this->anotherObj; // note also that we do not clone $this->shallowObj here, // meaning each instance of B will reference the same instance of $this->shallowObj } } $b1 = new B(); $b2 = clone $b1; var_dump(array( $b1, $b2 )); ?> /// output array(2) { [0]=> object(B)#1 (7) { ["what":protected]=> int(5) ["anotherObj":protected]=> object(stdClass)#3 (0) { } ["shallowObj":protected]=> object(stdClass)#4 (0) { } ["blah"]=> int(0) ["meh":protected]=> int(1) ["care":"A":private]=> int(2) ["someObj":"A":private]=> object(stdClass)#2 (0) { } } [1]=> object(B)#5 (7) { ["what":protected]=> int(5) ["anotherObj":protected]=> object(stdClass)#7 (0) { } ["shallowObj":protected]=> object(stdClass)#4 (0) { } ["blah"]=> int(0) ["meh":protected]=> int(1) ["care":"A":private]=> int(2) ["someObj":"A":private]=> object(stdClass)#6 (0) { } } } hope it helps! -nathan