Menu
Coddy logo textTech

A Palavra-chave final

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy — lição 24 de 91.

Embora a herança e a sobrescrita de métodos ofereçam flexibilidade, às vezes você precisa evitar que certas classes ou métodos sejam alterados. A palavra-chave final bloqueia seu código, garantindo que implementações específicas não possam ser alteradas por classes filhas.

Quando você marca um método como final, nenhuma classe filha pode sobrescrevê-lo:

<?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();

Saída:

ACC-1

O método getAccountId() não pode ser sobrescrito em SavingsAccount ou em qualquer outra classe filha. Isso protege a funcionalidade crítica que deve permanecer consistente em todos os tipos de conta.

Você também pode marcar uma classe inteira como final para evitar qualquer herança:

<?php
final class SecurityManager {
    public function authenticate($user) {
        return "Authenticating $user";
    }
}

$security = new SecurityManager();
echo $security->authenticate("admin");

Saída:

Authenticating admin

Nenhuma classe pode estender SecurityManager. Isso é útil para classes sensíveis à segurança ou quando o design da classe está completo e não deve ser modificado.

Ponto Chave: Use final em métodos para evitar a sobrescrita enquanto ainda permite a herança, ou em classes para impedir a herança completamente. É uma ferramenta para proteger código crítico que deve funcionar exatamente como projetado.

challenge icon

Desafio

Fácil

Vamos construir um sistema de gerenciamento de documentos que demonstra como a palavra-chave final protege funcionalidades críticas de serem modificadas por classes filhas.

Você criará três arquivos que trabalham juntos para gerenciar diferentes tipos de documentos, garantindo que certos recursos de segurança permaneçam bloqueados:

  • Document.php — Defina uma classe Document que serve como base para todos os documentos. Ela deve ter uma propriedade pública $title e uma propriedade protegida $author. O construtor aceita tanto o título quanto o autor. Inclua um método final chamado getSignature() que retorna "Signed by: " seguido pelo autor — este recurso de segurança nunca deve ser alterado por classes filhas. Adicione também um método regular getContent() que retorna "Document: " seguido pelo título.
  • Report.php — Defina uma classe Report que estende Document. Inclua o arquivo Document no topo. Esta classe adiciona uma propriedade $department. O construtor deve aceitar título, autor e departamento — use parent::__construct() para os dois primeiros e, em seguida, defina o departamento. Sobrescreva o método getContent() para retornar "Report: " seguido pelo título e o departamento entre parênteses, no formato "Report: [title] ([department])". A classe Report herda o método final getSignature() sem poder alterá-lo.
  • main.php — Inclua o arquivo Report. Você receberá três entradas: o título do documento, o nome do autor e o departamento. Crie um objeto Report com esses valores. Imprima o resultado de getContent() na primeira linha e, em seguida, imprima o resultado de getSignature() na segunda linha.

Este desafio mostra como os métodos final protegem funcionalidades críticas — a geração da assinatura permanece consistente em todos os tipos de documentos, enquanto outros métodos como getContent() podem ser personalizados por cada classe filha. O Report pode alterar como o conteúdo é exibido, mas o formato da assinatura está bloqueado na classe pai.

Folha de consulta

A palavra-chave final impede que classes ou métodos sejam modificados por classes filhas.

Métodos Finais: Marque um método como final para evitar que classes filhas o sobrescrevam:

<?php
class BankAccount {
    protected $balance;
    
    final public function getAccountId() {
        return "ACC-" . spl_object_id($this);
    }
}

class SavingsAccount extends BankAccount {
    // Cannot override getAccountId()
}

Classes Finais: Marque uma classe inteira como final para impedir qualquer herança:

<?php
final class SecurityManager {
    public function authenticate($user) {
        return "Authenticating $user";
    }
}

// No class can extend SecurityManager

Use final em métodos para proteger funcionalidades específicas enquanto permite a herança, ou em classes para impedir a herança inteiramente. Isso é útil para códigos sensíveis à segurança ou quando as implementações devem permanecer consistentes.

Experimente você mesmo

<?php
require_once 'Report.php';

// Ler entrada
$title = trim(fgets(STDIN));
$author = trim(fgets(STDIN));
$department = trim(fgets(STDIN));

// TODO: Criar um objeto Report com os valores de entrada

// TODO: Imprimir o resultado de getContent()

// TODO: Imprimir o resultado de getSignature()
?>
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos