Задача
Необходимо получить доступ к методам в родительском классе, которые были переопределены в дочернем классе.
Решение
Добавьте префикс parent:: к имени метода:
class shape {
function draw() {
// выводим на экран
}
}
class circle extends shape {
function draw($origin, $radius) {
// проверка данных
if ($radius > 0) {
parent::draw();
return true;
}
return false;
}
}
Обсуждение
Если подменить родительский метод путем определения его в дочернем методе, то родительский метод не будет вызван до тех пор, пока вы не сошлетесь на него явно.
В рассмотренном решении мы переопределяем метод draw() в дочернем классе circle, поскольку необходимо принять специфические для окружности параметры и проверить данные. Однако в данном случае мы еще хотим вызвать базовую функцию shape::draw(), которая фактически выполняет рисование, поэтому вызываем функцию parent::draw()
внутри метода, если значение переменной $radius больше 0.
Префикс parent:: может применяться только внутри класса. Вызов функции parent::draw() вне класса приведет к синтаксической ошибке. Например, если функция circle::draw() проверяла только радиус, а необходимо было вызвать также и функцию shape::draw(), то ничего бы не получилось:
$circle = new circle;
if ($circle->draw($origin, $radius)) {
$circle->parent::draw();
}
Если необходимо вызвать конструктор, принадлежащий к родительскому объекту, но неизвестно имя родительского класса, вызовите функцию get_parent_class() для динамического определения имени родителя, а затем объедините его с префиксом parent::, чтобы вызвать родительский конструктор:
class circle extends shape {
function circle() {
$parent = get_parent_class($this);
parent::$parent();
}
}
Функция get_parent_class() принимает имя класса или объект, а возвращает имя родителя объекта. Для поддержки общности передавайте $this, что является ссылкой на текущий объект. В этом случае возвращает shape. Затем используйте префикс parent::, чтобы быть уверенным в том, что PHP явно вызывает конструктор родительского класса.
Вызывая $parent() без префикса parent::, вы рискуете вызвать метод класса circle, который подменяет родительское определение.
Вызов функции parent::$parent() может выглядеть несколько странно. Однако PHP всего лишь заменяет переменную $parent на имя родительского класса. Теперь, поскольку после переменной стоят круглые скобки, PHP знает, что он должен вызвать метод.
Можно жестко прописать вызов функции parent::shape() прямо в конструкторе класса circle:
function circle() {
parent::shape();
}
Однако это не так гибко, как вызов функции get_parent_class(), хотя и быстрее, поэтому если известно, что иерархия объектов не будет изменяться, то такая замена может дать преимущество.
В заключение скажем, что нельзя составлять цепочки ключевых слов parent::, чтобы вернуться к классу прародителя, поэтому parent::parent:: foo() не работает.