Для понимания того, как соотносятся друг с другом внутренности классов, которые связаны наследованием, нужно разобраться с таким понятием как позднее связывание (late binding).
Вспомним базовый класс HTMLElement из прошлого урока. Внутри него активно используется $this
для обращения к свойствам:
<?php
// Базовый класс для всех тегов. Умеет работать с атрибутами.
class HTMLElement
{
public $attributes = [];
public function __construct($attributes = [])
{
$this->attributes = $attributes;
}
public function getAttribute(string $key)
{
return $this->attributes[$key];
}
}
Предположим, что мы создаём объект класса HTMLAnchorElement (который наследует HTMLElement). Тогда объектом какого класса будет $this
внутри методов родительского класса? Правильный ответ: HTMLAnchorElement, то есть того класса, объект которого мы прямо сейчас создаём.
<?php
class A
{
private $name = 'From A';
public function getName()
{
echo get_class($this);
echo "\n";
return $this->name;
}
}
class B extends A {}
$b = new B();
echo $b->getName();
echo "\n";
// => B
// => From A
https://repl.it/@hexlet/php-classes-late-binding-this
Эта особенность $this
называется поздним связыванием. Оно означает, что на момент определения класса, тип $this
неизвестен. В качестве текущего объекта может выступать объект любого класса, наследуемого от текущего. Всё выглядит так, как будто весь код внутри базового класса, скопировали и перенесли в каждый класс-наследник. Для позднего связывания не важно, насколько глубокая иерархия наследования. $this
всегда будет объектом того класса, который конструируется в коде.
Позднее связывание – важный элемент в работе наследования. Без него взаимодействие классов стало бы значительно сложнее и ограниченнее. Каждый объект должен был бы наверняка знать, к какому классу конкретно относятся свойства и методы в цепочке наследования. Понадобился бы специальный синтаксис для доступа к ним.
С другой стороны, в некоторых ситуациях позднее связывание не нужно. Например, константа ___CLASS___
всегда ссылается на тот класс, внутри которого она вызвана. В некоторых ситуациях такое поведение может быть полезно как минимум для отладки.
<?php
class A
{
public function whereIAm()
{
echo __CLASS__;
}
}
class B extends A {}
$obj = new B();
$obj->whereIAm(); // A
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.