Monday, February 02, 2009

PHP static as virtual self, what else for parent?

I find the static keyword in PHP 5.3 absolutely useful, but I instantly felt into a dilemma: what about parent?

With static it is possible to refer to a generic class static property, without referring the class where the method has been declared.
Here there is a simple example:

class Numbers {
public static $value = 0;
public static function getValue(){
return static::$value;
}
}

class One extends Number {
public static $value = 1;
}

class Two extends Number {
public static $value = 2;
}

$one = new One;
$two = new Two;
$one->getValue(); // 1
$two->getValue(); // 2

Above example shows how static behaves when an instance calls a method which uses static keyword.
Whatever subclass it is, we will always obtain the defined value (if any, otherwise the inherited one) as expected.

But what about parent behavior?

If we use parent inside a method it is like using self, the parent keyword will always refers to the parent class, if any, of the method which contains the parent keyword. If we add a function like this in the Numbers class:

public static function getParentValue(){
return parent::$value;
}

every subclass wont be able to show the Numbers $value and an error will be generated instead.

To obtain the desired result we have to use the ReflectionClass:

// class Numbers ...
public static function getParentValue(){
$class = new ReflectionClass($this);
return $class->getParentClass()->getStaticPropertyValue('$value');
}

Above code is much slower than parent::$value because of the instance creation plus its method call for each ReflectionClass instance ($this plus the one returned by getParentClass)

Now, the question is: is it truly necessary? Will we have other ways to retrieve a "static parent" from a method?

4 comments:

alemat13 said...

hi!
Is there an alternative solution for what you do in your first example using PHP 5.2.X?
Thanks.

Andrea Giammarchi said...

if you remove strict errors you could do something like this:
class Number {
public static $value = 0;
public function getValue(){
$class = get_class($this);
return $class::$value;
}
}
which means you cannot call that method as public static, but only via instances.

alemat13 said...

yes i tried that... but it doesn't fit what i needed... Furthermore, it's not allowed to do $class::$value in PHP 5.2.X.
Thank you anyway.

Andrea Giammarchi said...

sorry, I could not try that ... anyway, Reflection anybody?
class Number {
public static $value = 0;
public function getValue(){
$class = new ReflectionClass($this);
return $class->getStaticPropertyValue('value');
}
}
Regards