#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
- 1219 reads
vedro-compota
Mon, 09/25/2023 - 21:15
Permalink
хорошая тема, тут же должны
хорошая тема, тут же должны быть раскрыта разница между self:: и static::
_____________
матфак вгу и остальная классика =)