Hi all,

There has been some discussion on this list about late static binding
and the 'self' & 'parent' keywords. I'm looking to understand the
meaning of self:: and parent:: when used in the declaration of an
inherited class property or constant.

Based on discussions here and on comments to bugs like
http://bugs.php.net/bug.php?id=30934, my understanding is that self::
should be bound statically at compile time. Therefore, in the example
below, I would naively assume that self:: would always refer to class
A.

<?php
class A {
    const MY_CONST  = 'MY_CONST_A';

    public static $inheritedStatic = self::MY_CONST;
    public $inheritedProp = self::MY_CONST;
    const INHERITED_CONST = self::MY_CONST;
}

class B extends A {
    const MY_CONST  = 'MY_CONST_B';
}
?>

However, this is not the case. It seems that at compile time, the
engine flags class properties/constants that depend on class
constants. They are then subject to a one-off re-evaluation at
execution time. The flagging is done by setting the zval 'type' field
to IS_CONSTANT, IS_CONSTANT_ARRAY or IS_CONSTANT_INDEX. The
re-evaluation is done in zend_update_class_constants().

When self:: is involved, the result of this re-evaluation is not
always intuitive imho, and appears to contradict the idea that self::
is bound at compile time. See this test case for an illustration:
http://pastebin.com/f1d93fb2e

To summarize the behaviour exhibited by that test case:

1. An inherited static property's value depends on the order in which
classes are touched at execution time. The meaning of 'self' is fixed,
but depends on the scope in which zend_update_class_constants() is
first executed. Removing line 15 changes the outcome of the test.

2. An inherited instance property's value depends on the instantiated
class. When accessing the inherited property through an instance of A,
'self' is taken to mean A. When accessing it through an instance of B,
'self' is taken to mean 'B'. Presumably, this is because the property
is propagated to the subclass before its default value is evaluated.

3. Similarly to 2, an inherited constant's value depends on how it is
accessed. When accessing A::INHERITED_CONST, 'self' is taken to mean
A; when accessing B::INHERITED_CONST, 'self' is taken to mean B.

Is this as expected? I would argue that at least point 1 is a bug, but
would appreciate opinions before I investigate further.

(The exact same issues apply when using parent::. See this testcase:
http://pastebin.com/f249a0e8c )

Regards,
Robin

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to