Новое в PHP 5.3.0: Позднее статическое связывание
Поздним называется потому, что использование static:: будет означать вычисление класса/объекта, к которому будет относиться вызов, в момент вызова этой конструкции.
А статическим — потому что работает и для статических методов (но не только для них).
Для self:: и __CLASS__ всё по-старому — они ссылаются на класс, в котором определён метод.
Пример 1. Раннее связывание
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?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. Простой пример позднего статического связывания
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?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. Использование в нестатическом контексте
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?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. Переадресуемые и непереадресуемые вызовы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?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 ?> |