Переопределение методов

Взгляните еще раз на определение метода-конструктора _construct () из листинга 5. Видите, его список параметров отличается от списка конструктора FileLogger:: _construct()? А именно, мы передаем в конструктор нового класса лишь один аргумент - имя lоg-файла $fname, а логическое имя журнала вычисляем как basename ($fname). Получается, что мы переопределили в производном классе уже существующий в базовом классе метод, даже заменив при этом его прототип.

Вообще, под переопределением метода подразумевается его описание в производном классе, в то время как в базовом он уже имеется. Переопределенный метод может быть, например, написан "с нуля". Существует также возможность использования кода "родительской" функции (или любых других методов класса).

Модификаторы доступа при переопределении

Если вы переопределяете некоторый метод или свойство в производном классе, то должны указать у него такой же модификатор доступа, либо менее строгий. Например, при переопределении рrivаtе-функции допускается объявлять ее как protected или public. Наоборот, если в базовом классе присутствует public -метод, то в производном он тоже должен иметь модификатор public, в противном случае РНР выдаст сообщение об ошибке.

Доступ к методам базового класса

Чтобы избежать бесконечной рекурсии ("самовызова" метода), при вызове функции базового класса используется особый синтаксис с ключевым словом parent, например:

parent::_construct (...);

Обратите внимание, что $this при этом не упоминается!

Вообще, вместо $this->имяМетода () всегда допустимо использовать либо parent:: имяМетода(), sel f::имяМетода() или даже просто напрямую - File _ Logger::имяМетода () (предполагается, что File_Logger является текущим или родительским классом). При этом $this передается в вызываемую функцию автоматически.

Финальные методы

При написании метода вы можете явно запретить его переопределение в производных классах, используя модификатор final (листинг 6).

Листинг 6 Финальные методы. Файл final.php

При запуске этого несложного сценария выдается ошибка:

Fatal arror: Cannot override final method Base::test()

ПРИМЕЧАНИЕ

Для чего может понадобиться определять финальные методы? Предположим, что мы написали класс для работы с авторизованными пользователями, SecuredUser. В нем есть метод isSuperuser(), который выполняет необходимые проверки и возвращает true, если пользователь является суперпользователем. Такой метод имеет смысл сделать финальным, иначе кто-нибудь может написать производный класс InsecuredUser и "подменить" в нем метод isSuperuser () собственным, возвращающим true всегда. Так как применяется наследование, везде, где допустимо использование базового класса SecuredUser, возможно использование объекта производного класса InsecuredUser, а значит, могут быть проблемы с обеспечением безопасности в системе.

Запрет наследования

В РНР, как и в Java, можно не только запретить переопределение методов, но и запре­тить наследование от указанного класса вообще. Для этого ключевое слово final необходимо поставить перед определением класса, например:

final class Bаsе {} // Теперь нельзя создавать классы, производные от Base

Используйте final при описании класса только в тех случаях, когда это абсолютно необходимо, и вы уверены, что наследование к классу неприменимо.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: