views:

765

answers:

2

In PHP, if a static attribute is defined in the parent class, it cannot be overridden in a child class. But I'm wondering if there's any way around this.

I'm trying to write a wrapper for someone else's (somewhat clunky) function. The function in question can be applied to lots of different data types but requires different flags and options for each. But 99% of the time, a default for each type would suffice.

It would be nice if this could be done with inheritance, without having to write new functions each time. For example:

class Foo {
    public static $default = 'DEFAULT';

    public static function doSomething ($param = FALSE ) {
     $param = ($param === FALSE) ? self::$default : $param;
     return $param;
    }
}

class Bar extends Foo {
    public static $default = 'NEW DEFAULT FOR CHILD CLASS';
}

echo Foo::doSomething() . "\n"; 
// echoes 'DEFAULT'

echo Bar::doSomething() . "\n"; 
// echoes 'DEFAULT' not 'NEW DEFAULT FOR CHILD CLASS' 
// because it references $default in the parent class :(

Any suggestions? Is there a way around this behavior in PHP?

THANKS MUCH

+5  A: 

The forthcoming PHP 5.3.0 release includes late static binding, which might help. Using this feature you could use a static variable inside a static method, and let the late static binding take care of finding the "right" method.

class Foo {
    public static function getDefault() {
        static $default = 'DEFAULT';
        return $default;
    }
    public static function doSomething ($param) {
        $default=static::getDefault(); // here is the late static binding
        $param = ($param === FALSE) ? $default : $param;
        return $param;

    }
}

class Bar extends Foo {
     public static function getDefault() {
        static $default = 'NEW DEFAULT FOR CHILD CLASS';
        return $default;
    }
}
Paul Dixon
This would be lovely and thanks for the info. But alas, I need something that will run in my current production environment (5.2.6). THANKS!
Clayton
+4  A: 

Classic example of why using statics as globals (functions in this case) is a bad idea no matter the language.

The most robust method is to create multiple implementation sub classes of an abstract base "Action" class.

Then to try and remove some of the annoyance of instantiating an instance of the class just to call it's methods, you can wrap it in a factory of some sort.

For example:

abstract class AbstractAction {
  public abstract function do();
}

class FooAction extends AbstractAction {
  public function do() {
    echo "Do Foo Action";
  }
}

class BarAction extends AbstractAction {
  public function do() {
    echo "Do Bar Action";
  }
}

Then create a factory to "aid" in instantiation of the function

class ActionFactory {
  public static function get($action_name) {
    //... return AbstractAction instance here
  }  
}

Then use it as:

ActionFactory::get('foo')->do();
Allain Lalonde