note 91323 added to language.oop5.cloning
| From: | ben at last dot fm | Date: | Fri, 05 Jun 2009 17:33:07 +0000 |
| Subject: | note 91323 added to language.oop5.cloning | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-156403@lists.php.net to get a copy of this message | ||
Here are some cloning and reference gotchas we came up against at Last.fm.
1. PHP treats variables as either 'values types' or 'reference types', where the
difference is supposed to be transparent. Object cloning is one of the few times when it can make a
big difference. I know of no programmatic way to tell if a variable is intrinsically a value or
reference type. There IS however a non-programmatic ways to tell if an object property is value or
reference type:
<?php
class A { var $p; }
$a = new A;
$a->p = 'Hello'; // $a->p is a value type
var_dump($a);
/*
object(A)#1 (1) {
["p"]=>
string(5) "Hello" // <-- no &
}
*/
$ref =& $a->p; // note that this CONVERTS $a->p into a reference type!!
var_dump($a);
/*
object(A)#1 (1) {
["p"]=>
&string(5) "Hello" // <-- note the &, this indicates it's a reference.
}
*/
?>
2. unsetting all-but-one of the references will convert the remaining reference back into a value.
Continuing from the previous example:
<?php
unset($ref);
var_dump($a);
/*
object(A)#1 (1) {
["p"]=>
string(5) "Hello"
}
*/
?>
I interpret this as the reference-count jumping from 2 straight to 0. However...
2. It IS possible to create a reference with a reference count of 1 - i.e. to convert an property
from value type to reference type, without any extra references. All you have to do is declare that
it refers to itself. This is HIGHLY idiosyncratic, but nevertheless it works. This leads to the
observation that although the manual states that 'Any properties that are references to other
variables, will remain references,' this is not strictly true. Any variables that are
references, even to *themselves* (not necessarily to other variables), will be copied by reference
rather than by value.
Here's an example to demonstrate:
<?php
class ByVal
{
var $prop;
}
class ByRef
{
var $prop;
function __construct() { $this->prop =& $this->prop; }
}
$a = new ByVal;
$a->prop = 1;
$b = clone $a;
$b->prop = 2; // $a->prop remains at 1
$a = new ByRef;
$a->prop = 1;
$b = clone $a;
$b->prop = 2; // $a->prop is now 2
?>
----
Server IP: 92.48.74.199
Probable Submitter: 195.24.233.122
----
Manual Page -- http://www.php.net/manual/en/language.oop5.cloning.php
Edit -- https://master.php.net/note/edit/91323
Del: integrated -- https://master.php.net/note/delete/91323/integrated
Del: useless -- https://master.php.net/note/delete/91323/useless
Del: bad code -- https://master.php.net/note/delete/91323/bad+code
Del: spam -- https://master.php.net/note/delete/91323/spam
Del: non-english -- https://master.php.net/note/delete/91323/non-english
Del: in docs -- https://master.php.net/note/delete/91323/in+docs
Del: other reasons-- https://master.php.net/note/delete/91323
Reject -- https://master.php.net/note/reject/91323
Search -- https://master.php.net/manage/user-notes.php