#7.15 php ООП Позднее статическое связывание. Отличия self:: и static::. Использование static:: в нестатическом контексте
Primary tabs
Ранее в этой главе обсуждалось, что для доступа к статическому члену или константе класса из этого класса используется конструкция self::
. Ключевое словоself
всегда вычисляется как ссылка на тот класс, в котором определена использующая его функция. Поэтому в результате выполнения кода
<?php class Animal { const NAME = 'Animal'; public static function who() { echo "this is ", self::NAME; } } class Lion extends Animal { const NAME = 'Lion'; } Lion::who();
получим строку
this is Animal.
Для того, чтобы получить доступ к константе NAME
класса-наследника, вместо self
мы должны использовать ключевое слово static
:
<?php class Animal { const NAME = 'Animal'; public static function who() { echo "this is ", static::NAME; } } class Lion extends Animal { const NAME = 'Lion'; } Lion::who();
Теперь результатом будет строка
this is Lion.
Таким образом, использование static::
позволяет переопределять статические свойства, методы и константы в производных классах.
Внутреннее отличие использования self::
и static::
состоит в том, что имя класса, на который ссылается static
, определяется при исполнении соответствующей строки кода, тогда как значение self::NAME
вычисляется уже на этапе компиляции программы. Поэтому реализуемая с помощью конструкции static::
функциональность называется поздним статическим связыванием.
Использование static::
в нестатическом контексте
Возможно использование static::
в нестатическом контексте. Конструкция static::
в обычном (нестатическом) методе позволяет сослаться на класс, объект которого осуществляет соответствующий вызов. Например,
<?php class Animal { const NAME = 'Animal'; public function who() { echo "this is ", static::NAME; } } class Lion extends Animal { const NAME = 'Lion'; } $lion = new Lion; $lion->who();
Результатом будет:
this is Lion.
В нестатическом контексте $this->
и static::
часто могут быть взаимозаменяемы. Однако, в отличие от $this->
, конструкция static::
не позволяет ссылаться на нестатические переменные (ссылаться на нестатические методы с её помощью можно).
Существует ещё одно отличие. $this->
и static::
дадут разные результаты при обращении из метода базового класса к недоступному (private) переопределенному методу класса-наследника. Рассмотрим пример.
<?php class Animal { private function print_title() { echo "this is Animal<BR>"; } } class Lion extends Animal { } class Wolf extends Animal { private function print_title() { echo "this is Wolf<BR>"; } }
Класс Animal
имеет двух наследников Lion
и Wolf
, один из которых переопределяет private-метод print_title
базового класса.
Добавим в базовый класс Animal
метод test
для демонстрации различий использования конструкций $this->
и static::
при обращении к переопределенному private-методу, и создадим объекты классов-наследников:
<?php class Animal { private function print_title() { echo "this is Animal<BR>"; } public test() { $this->print_title(); static::print_title(); } } class Lion extends Animal { } class Wolf extends Animal { private function print_title() { echo "this is Wolf<BR>"; } } $lion = new Lion; $wolf = new Wolf;
Поскольку класс Lion
не переопределяет метод print_title
базового класса, то в результате вызова
$lion->test();
будут выполнены строки $this->print_title()
и static::print_title()
, которые дадут одинаковые результаты. А именно, в обоих случаях будет вызван метод print_title
базового класса, и на экран будут выведены строки:
this is Animal
this is Animal
При вызове
$wulf->test();
в результате выполнения строки $this->print_title()
PHP осуществит вызов соответствующего перекрытого метода "родного" класса (т.к. метод print_title
класса Wolf
недоступен), результатом которого снова будет строка
this is Animal
Наконец, строка static::print_title()
приведет к ошибке времени исполнения:
Fatal error: Uncaught Error: Call to private method Wolf::print_title() from scope Animal
,
поскольку в данном случае static
явно ссылается на имя класса Wolf
, метод которого print_title
не доступен из базового класса.
- Log in to post comments
- 711 reads
vedro-compota
Mon, 09/25/2023 - 21:15
Permalink
хорошая тема, тут же должны
хорошая тема, тут же должны быть раскрыта разница между self:: и static::
_____________
матфак вгу и остальная классика =)