Go Back   CodingForums.com > :: Server side development > PHP

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 02-15-2012, 11:00 AM   PM User | #1
timgolding
Senior Coder

 
timgolding's Avatar
 
Join Date: Aug 2006
Location: Southampton
Posts: 1,460
Thanks: 89
Thanked 110 Times in 109 Posts
timgolding is on a distinguished road
OOP cloning objects

in php 5.3 i noticed that you have to use clone to copy an object as using the = operator will copy by reference. Why is this? what would happen if you use &
e.g whats the differnece between
PHP Code:
$obj2 $obj
$obj3 
= &$obj;
$obj4 = clone $obj
__________________
You can not say you know how to do something, until you can teach it to someone else.
timgolding is offline   Reply With Quote
Old 02-15-2012, 11:55 AM   PM User | #2
KuriosJon
Regular Coder

 
Join Date: Jan 2012
Posts: 134
Thanks: 0
Thanked 32 Times in 32 Posts
KuriosJon is on a distinguished road
Let's test:

PHP Code:
class test {
    public 
$foo;
}

$test = new test();
$test -> foo 1;
echo 
$test -> foo;

$copy1 $test;
$copy2 = &$test;
$copy3 = clone $test;

echo 
'<hr>';
$test -> foo 2;
echo 
$copy1 -> foo;
echo 
$copy2 -> foo;
echo 
$copy3 -> foo;

echo 
'<hr>';
$copy1 -> foo 3;
echo 
$copy1 -> foo;
echo 
$copy2 -> foo;
echo 
$copy3 -> foo;

echo 
'<hr>';
$copy2 -> foo 4;
echo 
$copy1 -> foo;
echo 
$copy2 -> foo;
echo 
$copy3 -> foo;

echo 
'<hr>';
$copy3 -> foo 5;
echo 
$copy1 -> foo;
echo 
$copy2 -> foo;
echo 
$copy3 -> foo
Run that code, and you'll see that the cloned object is the only one that is not "linked" to the original object.
__________________
Roundabout Time Tracking
KuriosJon is offline   Reply With Quote
Users who have thanked KuriosJon for this post:
timgolding (02-15-2012)
Old 02-15-2012, 12:12 PM   PM User | #3
timgolding
Senior Coder

 
timgolding's Avatar
 
Join Date: Aug 2006
Location: Southampton
Posts: 1,460
Thanks: 89
Thanked 110 Times in 109 Posts
timgolding is on a distinguished road
So really theres no difference between
PHP Code:
$copy $test//and
$copy = &$test
when they designed this why didn't they keep the = construtor for making copies and the & for copying by reference as with all other data types. Or is all this to allow __clone to be called when cloning so you can run some additional code if need be?
__________________
You can not say you know how to do something, until you can teach it to someone else.
timgolding is offline   Reply With Quote
Old 02-15-2012, 02:43 PM   PM User | #4
Fou-Lu
God Emperor


 
Fou-Lu's Avatar
 
Join Date: Sep 2002
Location: Saskatoon, Saskatchewan
Posts: 15,658
Thanks: 4
Thanked 2,451 Times in 2,420 Posts
Fou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to allFou-Lu is a name known to all
Typical OO rules specify that you are provided with either the original memory or a link to the original memory (as in PHP and Java). The reference is different, but they both dereference to the same memory space.
Cloning is used to copy an object in its entirety to a new memory space. This includes all primitives and any reference to objects. So if you have a property that is an object, both the original and the clone will still share the same reference to the property and updates are reflected within both.
Objects are not created with an assignment. They are created when new is called on the class.

As for by reference, no they are different. Objects don't carry their memory pointers during assignment, they carry an object pointer which is simply a pointer to the memory location. Typical usage of the = &$obj will appear to function the same, but it is not and will not work in all situations:
PHP Code:
<?php

class A
{
    public 
$inner;
    public function 
__construct(B $inner)
    {
        
$this->inner $inner;
    }
}

class 
B
{
    public 
$desc;
    public function 
__construct($desc "I'm the first B")
    {
        
$this->desc $desc;
    }
}

$b = new B();
$a = new A($b);
$aCopy $a;
$aRef = &$a;
$aClone = clone $a;

// These will all say I'm the first B
print_r($a);
print_r($aCopy);
print_r($aRef);
print_r($aClone);


function 
modifyBValue(A $in)
{
    
$in->inner->desc "Value change in " __FUNCTION__;
}
print 
str_repeat('-'100) . PHP_EOL;
modifyBValue($a);
// These should now all indicate B value was changed in modifyBValue.
print_r($a);
print_r($aCopy);
print_r($aRef);
print_r($aClone);

function 
modifyB(A $in)
{
    
$in->inner = new B("Assigned in " __FUNCTION__);
}
print 
str_repeat('-'100) . PHP_EOL;
modifyB($a);
// These should now all indicate B object was changed in modifyB
print_r($a);
print_r($aCopy);
print_r($aRef);

// This should still say it was modified in modifyBValue:
print_r($aClone);

function 
modifyANonRef(A $in)
{
    
$in = new A(new B());
}

print 
str_repeat('-'100) . PHP_EOL;
modifyANonRef($a);
// None of these will change:
print_r($a);
print_r($aCopy);
print_r($aRef);
print_r($aClone);


// Here's where we see the difference in byref:
function modifyA(&$in// <-- This requires the & in order to modify the original variable and NOT the object pointer (which would have no effect)
{
    
$in = new A(new B());
}

print 
str_repeat('-'100) . PHP_EOL;
modifyA($a); // or just a $a = new A(new B()) would work too
// I'm the first B
print_r($a);

// Assigned in modifyB
print_r($aCopy);

// I'm the first B
print_r($aRef);

// Value change in modifyBValue
print_r($aClone);
So as you can see $aCopy = $a; and $aRef = &$a; do not actually do the same thing. There is limited situations for this, which would be the reassignment of a variable using a copy context in a function for example.
This is why when we say objects in PHP are passed by reference it is NOT actually true, but in MOST situations it seems that way. Objects in PHP are passed by OBJECT reference.

BTW, you can override __clone as well to perform a deep copy if you want. That would involve issuing a clone on the $inner in my example, which would make the $aClone never change to reflect that of $a.
Fou-Lu is offline   Reply With Quote
Users who have thanked Fou-Lu for this post:
timgolding (02-15-2012)
Reply

Bookmarks

Tags
clone, copying objects

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 07:22 PM.


Advertisement
Log in to turn off these ads.