Voting

: min(two, six)?
(Example: nine)

The Note You're Voting On

dodgie74 at NOSPAM dot yahoo dot NOSPAM dot co dot uk
17 years ago
As noted in bug #30934 (which is not actually a bug but a consequence of a design decision), the "self" keyword is bound at compile time. Amongst other things, this means that in base class methods, any use of the "self" keyword will refer to that base class regardless of the actual (derived) class on which the method was invoked. This becomes problematic when attempting to call an overridden static method from within an inherited method in a derived class. For example:

<?php
class Base
{
protected
$m_instanceName = '';

public static function
classDisplayName()
{
return
'Base Class';
}

public function
instanceDisplayName()
{
//here, we want "self" to refer to the actual class, which might be a derived class that inherits this method, not necessarily this base class
return $this->m_instanceName . ' - ' . self::classDisplayName();
}
}

class
Derived extends Base
{
public function
Derived( $name )
{
$this->m_instanceName = $name;
}

public static function
classDisplayName()
{
return
'Derived Class';
}
}

$o = new Derived('My Instance');
echo
$o->instanceDisplayName();
?>

In the above example, assuming runtime binding (where the keyword "self" refers to the actual class on which the method was invoked rather than the class in which the method is defined) would produce the output:

My Instance - Derived Class

However, assuming compile-time binding (where the keyword "self" refers to the class in which the method is defined), which is how php works, the output would be:

My Instance - Base Class

The oddity here is that "$this" is bound at runtime to the actual class of the object (obviously) but "self" is bound at compile-time, which seems counter-intuitive to me. "self" is ALWAYS a synonym for the name of the class in which it is written, which the programmer knows so s/he can just use the class name; what the programmer cannot know is the name of the actual class on which the method was invoked (because the method could be invoked on a derived class), which it seems to me is something for which "self" ought to be useful.

However, questions about design decisions aside, the problem still exists of how to achieve behaviour similar to "self" being bound at runtime, so that both static and non-static methods invoked on or from within a derived class act on that derived class. The get_class() function can be used to emulate the functionality of runtime binding for the "self" keyword for static methods:

<?php
class Base
{
protected
$m_instanceName = '';

public static function
classDisplayName()
{
return
'Base Class';
}

public function
instanceDisplayName()
{
$realClass = get_class($this);
return
$this->m_instanceName . ' - ' . call_user_func(array($realClass, 'classDisplayName'));
}
}

class
Derived extends Base
{
public function
Derived( $name )
{
$this->m_instanceName = $name;
}

public static function
classDisplayName()
{
return
'Derived Class';
}
}

$o = new Derived('My Instance');
echo
$o->instanceDisplayName();
?>

Output:
My Instance - Derived Class

I realise that some people might respond "why don't use just just the class name with ' Class' appended instead of the classDisplayName() method", which is to miss the point. The point is not the actual strings returned but the concept of wanting to use the real class for an overridden static method from within an inherited non-static method. The above is just a simplified version of a real-world problem that was too complex to use as an example.

Apologies if this has been mentioned before.

<< Back to user notes page

To Top