Позднее статическое связывание

Недавно наткнулся на интересную Late Static Bindings Explained, описывающую новую возможность OOP в PHP6, так называемое Late Static Binding (LSB).

Позднее статическое связывание также стало доступно, начиная с версии PHP 5.3.

Зачем нужен LSB

Сейчас, статическая ссылка на текущий класс, такая как self или __CLASS__ распознается используя класс в которому текущая функция принадлежит, например:

<?php
class A {
public static function who() {
     echo __CLASS__;
}
public static function test() { 
    self::who();
}
}
class B extends A {
public static function who() {
     echo __CLASS__;
}
}
B::test(); // A
?>

LSB пытается решить эту проблему используя новое ключевое слово static::, которое будет ссылкой на тот класс, который был вызван в текущий момент времени.

<?php
class A {
public static function who() {
     echo __CLASS__;
}
public static function test() { 
    static::who();
}
}
class B extends A {
public static function who() {
     echo __CLASS__;
}
}
B::test(); // B
?>

Такая конструкция вызовет метод A::test, но static:: будет ссылаться на класс B, при не статическом связывании, будет выщван метод A::who, так как $this-> следует правилал наследования, а static:: нет.

Примеры

Наиболее распостраненный случай:

<?php
class TestClass {
public static function who() {
     echo __CLASS__."\n";
}
public static function test() { 
    static::who();
}
}
class ChildClass1 extends TestClass {
public static function who() {
    echo __CLASS__."\n";
}
}
class ChildClass2 extends TestClass {}
TestClass::test(); // TestClass
ChildClass1::test(); // ChildClass1
ChildClass2::test(); // TestClass
?>
То же самое можно реализовать в не-статическом варианте:

<?php
class TestParent {
public static function who() {
     echo __CLASS__."\n";
}
public static function test() { 
    static::who();
}
}
class TestChild extends TestParent {
public function __construct() {
        static::who();
}
public function test() {
    $o = new TestParent();
}
public static function who() {
    echo __CLASS__."\n";
}
<}
$o = new TestChild; // TestChild
$o->test(); //TestParent
?>

Полное разрешении имен обрывает связь static:: с вызывающим классом и вызов A::who()  выведет A:

<?php
class A {
public static function who() {
     echo __CLASS__;
}
public static function test() { 
    static::who();
}
}
class B extends A {
public static function who() {
     echo __CLASS__;
}
public static function test() {
     A::who();
}
}
B::test(); // A
?>

Еще примеры

static:: также работает с такими методами как __get, __set …

<?php
class A {
protected static function who() {
     echo __CLASS__;
}
public function __get() { 
    return static::who();
}
}
class B extends A {
protected static function who() {
     echo __CLASS__;
}
}
$b = new B;
$b->foo; // B
?>
Теже самы принципы применимы и к обработчикам.

Leave a Reply