Menu
Coddy logo textTech

Ключевое слово 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 для методов, чтобы предотвратить переопределение, сохранив возможность наследования, или для классов, чтобы полностью запретить наследование. Это инструмент для защиты критически важного кода, который должен работать именно так, как задумано.

challenge icon

Задание

Легко

Давайте создадим систему управления документами, демонстрирующую, как ключевое слово final защищает критически важную функциональность от изменения дочерними class.

Вы создадите три файла, которые работают вместе для управления разными типами документов, гарантируя при этом, что определённые функции безопасности останутся заблокированными:

  • Document.php: Определите class Document, который служит базовым для всех документов. У него должно быть публичное свойство $title и защищённое свойство $author. Конструктор принимает title и author. Добавьте метод final с именем getSignature(), который возвращает "Signed by: [author]". Эта функция безопасности не должна изменяться дочерними class. Также добавьте обычный метод getContent(), который возвращает "Document: [title]".
  • Report.php: Определите class Report, который расширяет Document. В верхней части подключите файл Document. Этот class добавляет свойство $department. Конструктор должен принимать title, author и department: используйте parent::__construct() для первых двух, затем задайте department. Переопределите метод getContent(), чтобы он возвращал "Report: [title] ([department])". Class Report наследует метод 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()
?>
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор PHP