Prev: Netbeans XDebug Breakpoints Socket Accept
Next: Recupero di pen drive e memory card non più accessibili
From: Daniel Kolbo on 13 Jul 2010 20:29 Richard Quadling wrote: > On 12 July 2010 22:54, Daniel Kolbo <kolb0057(a)umn.edu> wrote: >> Richard Quadling wrote: >>> On 11 July 2010 23:19, Daniel Kolbo <kolb0057(a)umn.edu> wrote: >>>> Hello PHPers, >>>> >>>> I'm having some trouble understanding some PHP behaviour. The following >>>> example script exhibits the behaviour which I cannot understand. >>>> [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; >>>> $b = new B; >>>> $cee = new C; >>>> >>>> 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) >>>> >>>> ?> >>>> [/code] >>>> >>>> Why does $c->c print 'int 3' ? >>>> >>>> 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? >>>> >>>> Thanks in advance >>> >>> What do you think the value should be? >>> >>> A static property is bound to the class and not to an instance of the class. >>> >>> So, &A::$a is a reference to the static value. If you alter the value, >>> it will be altered for a subclasses of A and for any other reference >>> to it. >>> >> I think >> var_dump($c->c); would print object(B), but it's printing int 3. >> >> The reference is *not* being updated. I think this is a bug. What do >> you think? >> >> Thanks >> ` >> >> > > What version of PHP are you using? > I'm using: PHP Version 5.2.13
From: Daniel Kolbo on 13 Jul 2010 21:17 Richard Quadling wrote: > On 13 July 2010 09:46, Richard Quadling <rquadling(a)gmail.com> wrote: >> On 12 July 2010 22:54, Daniel Kolbo <kolb0057(a)umn.edu> wrote: >>> Richard Quadling wrote: >>>> On 11 July 2010 23:19, Daniel Kolbo <kolb0057(a)umn.edu> wrote: >>>>> Hello PHPers, >>>>> >>>>> I'm having some trouble understanding some PHP behaviour. The following >>>>> example script exhibits the behaviour which I cannot understand. >>>>> [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; >>>>> $b = new B; >>>>> $cee = new C; >>>>> >>>>> 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) >>>>> >>>>> ?> >>>>> [/code] >>>>> >>>>> Why does $c->c print 'int 3' ? >>>>> >>>>> 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? >>>>> >>>>> Thanks in advance >>>> >>>> What do you think the value should be? >>>> >>>> A static property is bound to the class and not to an instance of the class. >>>> >>>> So, &A::$a is a reference to the static value. If you alter the value, >>>> it will be altered for a subclasses of A and for any other reference >>>> to it. >>>> >>> I think >>> var_dump($c->c); would print object(B), but it's printing int 3. >>> >>> The reference is *not* being updated. I think this is a bug. What do >>> you think? >>> >>> Thanks > > Aha! > > $c = new C; > > At this stage $c->c will be a reference to the static A::$a = 3. > > $b = new B; > > Now, as B's constructor calls A's constructor which replaces the > static A::$a with a reference to the instance $b, the static A::$a > should now be $b > > $cee = new C; > > At this stage $cee->c will be a reference to the static A::$a = $b. > > But, when var_dump()'d, $c->c !== $cee->c, and I think they should as > both have been assigned to a reference of a static. > > It would seem to be a bug. > > I get the same output for V5.0.0 to V5.3.3RC2 > Thanks for confirming. I reported the bug. I shortened up the test script quite a bit. Please see: Bug #52332 http://bugs.php.net/bug.php?id=52332 `
From: "Ford, Mike" on 14 Jul 2010 05:10 > -----Original Message----- > From: Daniel Kolbo [mailto:kolb0057(a)umn.edu] > 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(a)leedsmet.ac.uk 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
From: David Harkness on 14 Jul 2010 15:28 Ah, so assigning a reference to a variable already holding a reference changes that variable's reference only in the same way that unsetting a reference doesn't unset the other variables referencing the same thing, yes? $a = 5; $b = &$a; print $a; > 5 unset($b); // does not affect $a print $a; > 5 // and according to Mike's previous message $b = &$a; $c = 10; $b = &$c; // does not affect $a print $a > 5 That makes a lot of sense. If it didn't work this way there would be no easy way to untangle references. In the case of foreach($array as $key => &$value) { ... } the first value in the array would continuously be overwritten by the next value. 1. $value gets reference to first array value 2. on each step through the loop, the first array value would be overwritten by the next value in the loop since $value is forever tied to it by the initial reference assignment. That would be a Bad Thing (tm). Thanks for the clarification, Mike. David
From: Daniel Kolbo on 14 Jul 2010 20:29 David Harkness wrote: > Ah, so assigning a reference to a variable already holding a reference > changes that variable's reference only in the same way that unsetting a > reference doesn't unset the other variables referencing the same thing, yes? > > $a = 5; > $b = &$a; > print $a; >> 5 > unset($b); // does not affect $a > print $a; >> 5 > > // and according to Mike's previous message > $b = &$a; > $c = 10; > $b = &$c; // does not affect $a > print $a >> 5 > > That makes a lot of sense. If it didn't work this way there would be no easy > way to untangle references. In the case of > > foreach($array as $key => &$value) { ... } > > the first value in the array would continuously be overwritten by the next > value. > > 1. $value gets reference to first array value > 2. on each step through the loop, the first array value would be overwritten > by the next value in the loop since $value is forever tied to it by the > initial reference assignment. > > That would be a Bad Thing (tm). > > Thanks for the clarification, Mike. > > David > The big "aha" moment for was when realizing that when assigning a reference to a variable you only change its reference and not any other variable that may also have shared the same reference. Yuck that's a mouth full. This happened when Mike said, " NOTE: since we are assigning a new reference to a variable which is already a reference, ONLY this reference changes". Yes, i agree with you David (on both of your points). Thanks for the example using the unset. This further clarified/solidified my understanding. Now, with this new understanding, I also wish to comment that if i assign (without reference) $this, i don't have to be too worried about bloating the memory, b/c i'm only assigning/copying the identifer or *handle* and not the actual object itself. In case, someone reads this in the archive the link is: http://php.net/manual/en/language.oop5.references.php Mike, thank you a ton. Regards. `
First
|
Prev
|
Pages: 1 2 Prev: Netbeans XDebug Breakpoints Socket Accept Next: Recupero di pen drive e memory card non più accessibili |