Ключевое слово final
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy. Урок 24 из 91.
Хотя наследование и переопределение методов обеспечивают гибкость, иногда необходимо предотвратить изменение определённых классов или методов. Ключевое слово final фиксирует ваш код, гарантируя, что дочерние классы не смогут изменить определённые реализации.
Если пометить method как final, ни один дочерний класс не сможет выполнить его override:
<?php
class BankAccount {
protected $balance;
public function __construct($balance) {
$this->balance = $balance;
}
final public function getAccountId() {
return "ACC-" . spl_object_id($this);
}
}
class SavingsAccount extends BankAccount {
public function addInterest() {
return $this->balance * 0.05;
}
}
$account = new SavingsAccount(1000);
echo $account->getAccountId();
Вывод:
ACC-1Метод getAccountId() нельзя переопределить в SavingsAccount или любом другом дочернем классе. Это защищает критически важную функциональность, которая должна оставаться неизменной для всех типов account.
Вы также можете пометить весь класс как final, чтобы предотвратить любое наследование:
<?php
final class SecurityManager {
public function authenticate($user) {
return "Authenticating $user";
}
}
$security = new SecurityManager();
echo $security->authenticate("admin");
Вывод:
Authenticating adminНи один class не может extend SecurityManager. Это полезно для классов, где важна безопасность, или когда проектирование class завершено и его не следует изменять.
Ключевой момент: Используйте final для методов, чтобы предотвратить переопределение, сохранив возможность наследования, или для классов, чтобы полностью запретить наследование. Это инструмент для защиты критически важного кода, который должен работать именно так, как задумано.
Задание
ЛегкоДавайте создадим систему управления документами, демонстрирующую, как ключевое слово final защищает критически важную функциональность от изменения дочерними class.
Вы создадите три файла, которые работают вместе для управления разными типами документов, гарантируя при этом, что определённые функции безопасности останутся заблокированными:
Document.php: Определите classDocument, который служит базовым для всех документов. У него должно быть публичное свойство$titleи защищённое свойство$author. Конструктор принимает title и author. Добавьте методfinalс именемgetSignature(), который возвращает"Signed by: [author]". Эта функция безопасности не должна изменяться дочерними class. Также добавьте обычный методgetContent(), который возвращает"Document: [title]".Report.php: Определите classReport, который расширяетDocument. В верхней части подключите файл Document. Этот class добавляет свойство$department. Конструктор должен принимать title, author и department: используйтеparent::__construct()для первых двух, затем задайте department. Переопределите методgetContent(), чтобы он возвращал"Report: [title] ([department])". ClassReportнаследует методgetSignature(), помеченный как final, и не может его изменить.main.php: Подключите файл Report. Вы получите три входных значения: title документа, имя author и department. Создайте объектReportс этими значениями. Выведите result методаgetContent()в первой строке, затем выведите result методаgetSignature()во второй строке.
Это задание показывает, как методы final защищают критически важную функциональность: генерация подписи остаётся одинаковой для всех типов документов, в то время как другие методы, такие как getContent(), могут настраиваться каждым дочерним class. Class Report может изменить способ отображения содержимого, но формат подписи зафиксирован в родительском class.
Попробуйте сами
<?php
require_once 'Report.php';
// Чтение ввода
$title = trim(fgets(STDIN));
$author = trim(fgets(STDIN));
$department = trim(fgets(STDIN));
// TODO: Создать объект Report с входными значениями
// TODO: Вывести результат getContent()
// TODO: Вывести результат getSignature()
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Повторение — простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыПовторение — иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateМодификаторы доступа подробноГеттеры и сеттерыСокрытие информацииПродвижение конструктора (8.0)Повторение — система учёта студентов2Пространства имён и автозагрузка
Введение в пространства имёнКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerПовторение — структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс и абстрактный классАннотация типов с интерфейсамиПовторение — калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeПовторение — пользовательская коллекция3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищённые свойстваСвойства только для чтения (PHP 8.1)Повторение — менеджер банковского счёта6Полиморфизм
Повторение переопределения методовПолиморфизм через интерфейсыАннотации типов и объединённые типыПозднее статическое связываниеПовторение — обработчик платежей9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования, часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн StrategyПотренируйтесь самостоятельно: Онлайн-компилятор PHP