#47384 [Bgs]: static references resolved incorrectly with class inheritance

From: Date: Mon, 11 Jan 2010 00:15:35 +0000
Subject: #47384 [Bgs]: static references resolved incorrectly with class inheritance
References: 1  Groups: php.doc.bugs 
Request: Send a blank email to doc-bugs+get-3672@lists.php.net to get a copy of this message
 ID:               47384
 User updated by:  alreece45 at gmail dot com
 Reported By:      alreece45 at gmail dot com
 Status:           Bogus
 Bug Type:         Documentation problem
 Operating System: *
 PHP Version:      5.*, 6
 New Comment:

I understand your point with static properties, however:

A) because the $name property is defined in Father, it should be using

the "self" as seen from Father (as happens when you use the constant 
from a method like __construct). If this is not the expected case, the

documentation should be clarified that using self changes depending on

the context. 

The following code should ALWAYS set the property to the same value 
when defined in the same class (regardless of child classes).

1)  public $var = self::someConstant;
2) 
  function __construct() {
    $this->var = self::someConstant;
  }

B) Because both class constants and static properties and methods are 
tied to a class definition. It should be documented with class 
constants whether or not they are static.

C) I incorrectly concluded when writing the test case that the object 
instance affected non-static properties (I encountered the bug in a 
more complex code-base). However, it does affect the values when  
static properties are used (another example included below).

<?php
       class Father {
               const my_name = 'Father';
               public static $name = self::my_name;
       }
       class Son extends Father {
               const my_name = 'Son';
               public static $daddy = parent::my_name;
       }
       class GrandSon extends Son {
               const my_name = 'Grandchild';
       }
       // new Father(); // uncommenting this line affects output
       echo Grandson::$name  . "\n"; // outputs Grandchild
       echo Grandson::$daddy . "\n"; // outputs Son
 
?>


Previous Comments:
------------------------------------------------------------------------

[2010-01-10 21:36:09] degeberg@php.net

Using PHP 5.3.1, I get "Grandson" then "Child" regardless of the $temp
object's presence.

I think you're confusing class constants
(http://php.net/oop5.constants) with static properties
(http://php.net/oop5.static). Despite similar syntax for accessing them,
they do not behave the same way.

Static properties are bound to the defining class. Regular (non-static)
properties are bound to the object. Seeing as the object does not exist
prior to its instantiation, the value is not bound before that happens.

------------------------------------------------------------------------

[2010-01-10 19:35:52] alreece45 at gmail dot com

Again, not bogus, the value of the property $name depends on the order

the objects are created. 

Even if the expected behavior makes late static binding possible with 
the self keyword instead of the static keyword. That use is not yet 
documented, and then the following would become unexpected as it now 
displays "Father, Father" both times (instead of "Son, Grandson" when 
an instance of Father is not made). 

The value of the property should not depend on the order of the 
objects initiated.

New Reproduce Code (Does not replace the previous test script, the 
original test script output is still the same, and the bug still 
holds):

<?php
	class Father {
		const my_name = 'Father';
		public $name = self::my_name;
	}
	class Son extends Father {
		const my_name = 'Son';
		public $daddy = parent::my_name;
	}
	class GrandSon extends Son {
		const my_name = 'Grandchild';
	}
	$temp = new Father;
	$older = new GrandSon;
	echo "{$older->name}\n"; // outputs Father
	echo "{$older->daddy}\n"; // outputs Father
?>

------------------------------------------------------------------------

[2010-01-10 13:37:01] degeberg@php.net

Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to
report
a bug at http://bugs.php.net/how-to-report.php

This is expected behavior. Note that there is a difference between
class constants and static class properties. Regular, non-static
properties are set when an object is constructed.

Upon construction of a GrandSon object, self::my_name would
'Grandchild' and parent::my_name would contain 'Son'. You can achieve
the kind of behavior you're looking for using static properties:

<?php
class Father {
	public static $my_name = 'Father';
	public $name;
	
	public function __construct() {
		$this->name = self::$my_name;
	}
}
class Son extends Father {
	static $my_name = 'Son';
	public $daddy;
	
	public function __construct() {
		parent::__construct();
		$this->daddy = parent::$my_name;
	}
}
class GrandSon extends Son {
	static $my_name = 'Grandchild';
}

$older = new GrandSon;
echo "{$older->name}\n";
echo "{$older->daddy}\n";
?>

------------------------------------------------------------------------

[2009-11-23 14:54:31] vrana@php.net

If the variable is initialized in the constructor then it gives the
expected output:

function __construct() {
	$this->name = self::my_name;
}

So this is specific to initialization in the declaration.

------------------------------------------------------------------------

[2009-11-20 13:40:24] alreece45 at gmail dot com

Again, this is NOT the difference between self and static, this is the

self keyword behaving like static when it shouldn't.

------------------------------------------------------------------------

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/47384

-- 
Edit this bug report at http://bugs.php.net/?id=47384&edit=1



Thread (8 messages)

« previous php.doc.bugs (#3672) next »