Позднее статическое связывание
Недавно наткнулся на интересную 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
?>
