Новое в PHP 5.3.0: Позднее статическое связывание
Поздним называется потому, что использование static:: будет означать вычисление класса/объекта, к которому будет относиться вызов, в момент вызова этой конструкции.
А статическим — потому что работает и для статических методов (но не только для них).
Для self:: и __CLASS__ всё по-старому — они ссылаются на класс, в котором определён метод.
Пример 1. Раннее связывание
<?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
?>
Использование позднего статического связывания
В отличие от предыдущего примера, использование позднего статического связывания (при помощи static::) позволяет попробовать обратиться к методу первоначально вызванного класса на этапе выполнения.
Таким образом, предыдущий пример превращается в:
Пример 2. Простой пример позднего статического связывания
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();//вывод: B
?>
Надо заметить, что static:: — не то же самое для класса, что и $this-> для объекта ($this-> следует правилам наследования, а static:: — нет).
Пример 3. Использование в нестатическом контексте
<?php
class TestChild extends TestParent {
public function __construct() {
static::who();
}
public function test() {
$o = new TestParent();
}
public static function who() {
echo __CLASS__."\n";
}
}
class TestParent {
public function __construct() {
static::who();
}
public static function who() {
echo __CLASS__."\n";
}
}
$o = new TestChild;//вывод: TestChild
$o->test();//вывод: TestParent
?>
Позднее статическое связывание не пойдёт выше, к предкам, а остановится на вызове метода инициировавшего его класса, тогда как self:: и parent:: будут всети себя согласно правилам наследования.
Пример 4. Переадресуемые и непереадресуемые вызовы
<?php
class A {
public static function foo() {
static::who();
}
public static function who() {
echo __CLASS__."\n";
}
}
class B extends A {
public static function test() {
A::foo();
parent::foo();
self::foo();
}
public static function who() {
echo __CLASS__."\n";
}
}
class C extends B {
public static function who() {
echo __CLASS__."\n";
}
}
C::test();
//вывод:
//A
//C
//C
?>