RE: Static Class Member References

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Daniel Kolbo [mailto:kolb0057@xxxxxxx]
> Sent: 11 July 2010 23:19
> 
> Hello PHPers,
> 
> I'm having some trouble understanding some PHP behaviour.  The
> following
> example script exhibits the behaviour which I cannot understand.

I'm pretty sure that this is *not* a bug. I'll answer your last
question first, and then demonstrate with your code.

> I'm nervous to use "self::$a = $this;" because I don't want to be
> copying the whole object.  However, isn't $this just a reference to
> the
> object, so "self::$a = $this;" is just copying the reference and not
> the
> actual object, right?

Not exactly, although everybody seems to refer to it as a reference
for convenience. Most of the time it doesn't matter, but when you
start introducing references to objects it can - it's better to think
of an object variable as holding the object's *handle*
(see http://php.net/anguage.oop5.references.php for more on this), so
it's clear exactly what a reference is referencing.

Now for your code:

> [code]
> <?php
> 
> class A
> {
> 	public static $a = 3;
> 
> 	function __construct()
> 	{
> 		//self::$a = $this; //[i]
> 		self::$a =& $this; //[ii]
> 	}
> }
> 
> class B extends  A
> {
> 	function __construct()
> 	{
> 		parent::__construct();
> 	}
> }
> 
> class C {
> 	var $c;
> 
> 	function __construct()
> 	{
> 		$this->c =& A::$a;
> 	}
> 
> }
> 
> 
> $c = new C;

[i] & [ii]  in C::__construct(): $c->c = reference to same value as
            A::$a (currently (int)3)
            NOTE: because of how references work, A::$a is now also a
            reference to (int)3.

> $b = new B;

[i]  in A::__construct(): A::$a = handle of object B(1) (also assigned to
     global $b)
     NOTE: $c->c, as reference to $A::a, now also references handle of
           object B(1)

[ii] in A::__construct(): A::$a = reference to handle of object B(1)
     NOTE: since we are assigning a new reference to a variable which is
           already a reference, ONLY this reference changes -- so $c->c
           is still a reference to (int)3...!

> $cee = new C;

Irrelevant -- the damage has already been done!

> var_dump($c->c); // [i] prints object(B), but [ii] prints int 3
> var_dump($cee->c); // [i] prints object(B), and [ii] prints
> object(B)

... which is correct according to my interpretation.

This has been such a regular confusion, that some time ago I wrote
this test script:

<?php

	class test {

		public $me;
	}

	$t = new test;
	$t->me = 'Original';

	$copy_t = $t;
	$ref_t = &$t;

	$copy_t = new test;
	$copy_t->me = 'Altered Copy';

	echo <<<RESULT1
	Original: $t->me<br />
	Copy: $copy_t->me<br />
	Reference: $ref_t->me<br />
RESULT1;

	$ref_t = new test;
	$ref_t->me = 'Altered Reference';

	echo <<<RESULT2
	<br />
	Original: $t->me<br />
	Copy: $copy_t->me<br />
	Reference: $ref_t->me<br />
RESULT2;


	$s = 'String';

	$copy_s = $s;
	$ref_s = &$s;

	$copy_s = 'String Copy';

	echo <<<RESULT3
	<br />
	Original: $s<br />
	Copy: $copy_s<br />
	Reference: $ref_s<br />
RESULT3;

	$ref_s = 'String Reference';

	echo <<<RESULT4
	<br />
	Original: $s<br />
	Copy: $copy_s<br />
	Reference: $ref_s<br />
RESULT4;

?>

Which gives this output:

	Original: Original
	Copy: Altered Copy
	Reference: Original

	Original: Altered Reference
	Copy: Altered Copy
	Reference: Altered Reference

	Original: String
	Copy: String Copy
	Reference: String

	Original: String Reference
	Copy: String Copy
	Reference: String Reference

Which demonstrates how exactly the behaviour of objects correlates to
scalars with regards to copying and referencing -- but may not be
exactly what you expect if you think of object variables as always
holding a reference to the object. I would heartily recommend always
to think of an object variable as holding the object's *handle*, and
*not* a reference - this may croggle your brain a bit, but makes it a
Lot clearer what's happening in edge cases like this.

Cheers!

Mike

 -- 
Mike Ford,
Electronic Information Developer, Libraries and Learning Innovation,  
Leeds Metropolitan University, C507, Civic Quarter Campus, 
Woodhouse Lane, LEEDS,  LS1 3HE,  United Kingdom 
Email: m.ford@xxxxxxxxxxxxxx 
Tel: +44 113 812 4730





To view the terms under which this email is distributed, please go to http://disclaimer.leedsmet.ac.uk/email.htm

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php




[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux