#47384 [Bgs]: static references resolved incorrectly with class inheritance
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)