Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When would you need to use late static binding?

Tags:

oop

php

After reading this description of late static binding (LSB) I see pretty clearly what is going on. Now, under which sorts of circumstances might that be most useful or needed?

like image 734
rg88 Avatar asked Sep 17 '08 20:09

rg88


People also ask

What is late static binding?

Whenever a PHP interpreter gets the request to compile a function. If it sees any static property, then it leaves the property pending for run time and the property gets its value during runtime from the function it is being called. This is called late static binding.

What is the purpose of late static binding in PHP?

The concept of late static bindings brings in a new keyword 'static', which when used, binds the function to the runtime class, or the class where the function was first used. In addition to this, any static function or variable is usually executed during runtime and not during compile time.

What is late binding and early binding in PHP?

If the compiler knows at the compile-time which function is called, it is called early binding. If a compiler does not know at compile-time which functions to call up until the run-time, it is called late binding.

What is new static () in PHP?

New static: The static is a keyword in PHP. Static in PHP 5.3's late static bindings, refers to whatever class in the hierarchy you called the method on. The most common usage of static is for defining static methods.


2 Answers

I needed LSB this for the following scenario:

  • Imagine you're building a "mail processor" daemon that downloads the message from an email server, classifies it, parses it, saves it, and then does something, depending on the type of the message.
  • Class hierarchy: you have a base Message class, with children "BouncedMessage" and "AcceptedMessage".
  • Each of the message types has its own way to persist itself on disk. For example, all messages of type BouncedMessage try to save itself as BouncedMessage-id.xml. AcceptedMessage, on the other hand, needs to save itself differently - as AcceptedMessage-timestamp.xml. The important thing here is that the logic for determining the filename pattern is different for different subclasses, but shared for all items within the subclass. That's why it makes sense for it to be in a static method.
  • Base Message class has an abstract static method (yes, abstract AND static) "save". BouncedMessage implements this method with a concrete static method. Then, inside the class that actually retrieves the message, you can call "::save()"

If you want to learn more about the subject:

  • http://www.qcodo.com/forums/topic.php/2356
  • http://community.livejournal.com/php/585907.html
  • http://bugs.php.net/bug.php?id=42681
like image 123
Alex Weinstein Avatar answered Oct 05 '22 19:10

Alex Weinstein


One primary need I have for late static binding is for a set of static instance-creation methods.

This DateAndTime class is part of a chronology library that I ported to PHP from Smalltalk/Squeak. Using static instance-creation methods enables creation of instances with a variety of argument types, while keeping parameter checking in the static method so that the consumer of the library is unable to obtain an instance that is not fully valid.

Late static binding is useful in this case so that the implementations of these static instance-creation methods can determine what class was originally targeted by the call. Here is an example of usage:

With LSB:

class DateAndTime {

    public static function now() {
        $class = static::myClass();
        $obj = new $class;
        $obj->setSeconds(time());
        return $obj;
    }

    public static function yesterday() {
        $class = static::myClass();
        $obj = new $class;
        $obj->setSeconds(time() - 86400);
        return $obj;
    }

    protected static function myClass () {
        return 'DateAndTime';
    }
}

class Timestamp extends DateAndTime {

    protected static function myClass () {
        return 'Timestamp';
    }
}


// Usage:
$date = DateAndTime::now();
$timestamp = Timestamp::now();

$date2 = DateAndTime::yesterday();
$timestamp2 = Timestamp::yesterday();

Without late static binding, [as in my current implementation] each class must implement every instance creation method as in this example:

Without LSB:

class DateAndTime {

    public static function now($class = 'DateAndTime') {
        $obj = new $class;
        $obj->setSeconds(time());
        return $obj;
    }

    public static function yesterday($class = 'DateAndTime') {
        $obj = new $class;
        $obj->setSeconds(time() - 86400);
        return $obj;
    }

}

class Timestamp extends DateAndTime {

    public static function now($class = 'Timestamp') {
        return self::now($class);
    }

     public static function yesterday($class = 'Timestamp') {
        return self::yesterday($class);
    }

}

As the number of instance-creation methods and class-hierarchy increases the duplication of methods becomes a real pain in the butt. LSB reduces this duplication and allows for much cleaner and more straight-forward implementations.

like image 44
Adam Franco Avatar answered Oct 05 '22 20:10

Adam Franco