Late static binding….sorta :/

The good news is late static binding has been introduced into head and looks like it will be merged into 5.3 before it is released. The horrible news is I really don’t think the patch went as far as it needs to.

If you look at the original posts that cropped up about a year and a half ago the whole purpose of late static binding was to allow the same kind of flexibility provided by inheritance of standard class methods for static methods, properties, and constants. This wouldn’t really open the door for any grandios, new kind of applications, it would just allow a new way to code libraries the most prominant example being an Active Record Library.

This is now possible, however I think there is a very unfortunate limitation that I brought up a few times on the Internals mailing list to apparently no avail. The problem is with the fact that static will ALWAYS return the ‘resolved’ name of the class used to call the current function. So, imagine the following method:

class Foo
{
    //...

    static public function test()
    {
        return static::$some_property;
    }

    //...
}

class Bar extends Foo
{
}

If you call test using Foo::test() then static:: will resolve to the ‘Foo’ class. If you call it using Bar::test() then static:: will resolve to ‘Bar’. This is correct and works well for simple inheritance. However things start taking a downward turn the more you use inheritance. Consider the following change to Bar and the addition of a new class Bar_Child:

class Foo
{
    //...

    static public function test()
    {
        return static::$some_property;
    }

    //...
}

class Bar extends Foo
{
    static public function test()
    {
        // Do some work specific to Bar

        return parent::test();
    }
}

class Bar_Child extends Bar
{
}

Now, calling Foo::test() will again result in static:: being bound to ‘Foo’. However, due to the fact that parent:: will resolve to Foo:: that means the call Bar::test() will now result in static:: being bound to ‘Foo’. Bar_Child::test() will do exactly the same thing, static:: will again be bound to ‘Foo’. This is incredibly inflexible and in my opinion this is the exact problem that ‘late static binding’ is SUPPOSED to fix.

There are a couple of ways to fix this that I can think of right now, unfortunately nobody on list seems very motivated to explore any compromises. The two ways that come to mind immediately are either setting the behavior of parent:: such that it forwards the calling class through the next function call. So in the example above, calling Bar::test() will still result in calling Foo::test() however it will not ‘reset’ the calling class so that static:: will still resolve to ‘Bar::’, likewise Bar_Child::test() will result in static:: being bound to ‘Bar_Child’.

The second alternative is introducing another scope. I have no clue what this scope would be called, but it would basically implement the functionality I just described for parent:: above but would do it using a new keyword so parent:: could remain the same.

Dmitry Stogov mentioned my first alternative on the list however he also included this functionality for the self:: scope which I could see causing some serious problems. In either case, I am thankful that the functionality has started to make its way in, but I can’t help but think that myself and some other early proponents of the functionality are getting completely shafted.

Share
This entry was posted in PHP. Bookmark the permalink.

4 Responses to Late static binding….sorta :/

  1. The patch as it stands has basically all the same problems as it was supposed to solve this makes me SO mad!

    Thanks for your effort in trying to point this out to everyone.

  2. Yipee! Another “half” feature in PHP 5.3. This is shaping up to be quite the half release. ;-)

    /me goes to pick a new copy of Programming Python

  3. James Harris says:

    Speaking of Python, I had hoped that ‘Late Static Binding’ would give us a feature parallel to Python’s ‘classmethod’, but from what you’ve shown here that doesn’t seem to be the case.

    I’m not really sure how useful the proposed behavior is going to be at all. Another half-feature for PHP, not impressed.

    Sorry for preaching to the choir, please direct me to the complaints department :P

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>