final
A palavra-chave "final" em PHP permite marcar uma classe, método ou constante como final, impedindo que subclasses os modifiquem ou redeclarem.
A Palavra-chave final do PHP
final é uma palavra-chave de orientação a objetos em PHP que bloqueia parte de uma classe para que subclasses não possam alterá-la. Você pode aplicá-la a uma classe (nenhuma outra classe pode estendê-la), a um método (nenhuma subclasse pode substituí-lo) ou, desde o PHP 8.1, a uma constante (nenhuma subclasse pode redefini-la).
Marcar algo como final é uma declaração deliberada de design: "este comportamento é intencional e as classes filhas não devem alterá-lo." Bem utilizado, previne substituições acidentais, documenta a intenção no código e permite raciocinar sobre uma classe sem se preocupar que uma subclasse tenha silenciosamente alterado seu funcionamento. Esta página aborda cada forma de final, quando usá-lo e as armadilhas que costumam pegar as pessoas de surpresa.
Já familiarizado com subclasses e substituições?
finalsó faz sentido no contexto de herança em PHP e classes e objetos.
Classes finais
Uma classe final não pode ser estendida. Qualquer tentativa de declarar uma subclasse produz um erro fatal em tempo de compilação:
<?php
final class PaymentGateway
{
public function charge(float $amount): string
{
return "Charged $amount";
}
}
// Fatal error: Class CryptoGateway cannot extend final class PaymentGateway
class CryptoGateway extends PaymentGateway {}Use uma classe final quando seu comportamento é completo e a herança seria um uso indevido — por exemplo, um objeto de valor, um serviço cujo contrato você controla, ou uma classe sensível à segurança onde uma subclasse que sobrescreve poderia contornar uma verificação.
Métodos finais
Você pode manter uma classe extensível, mas bloquear métodos individuais. Um método final pode ser herdado e chamado por subclasses, mas não pode ser substituído:
<?php
class Account
{
protected float $balance = 0;
// Subclasses may add behavior, but must not change how withdrawing works.
final public function withdraw(float $amount): void
{
if ($amount > $this->balance) {
throw new RuntimeException("Insufficient funds");
}
$this->balance -= $amount;
}
}
class SavingsAccount extends Account
{
public function addInterest(float $rate): void
{
$this->balance += $this->balance * $rate;
}
// Fatal error: Cannot override final method Account::withdraw()
// public function withdraw(float $amount): void {}
}Este é o uso mais comum de final: você deseja que uma classe seja aberta para extensão em geral, mas um método específico impõe um invariante (aqui, nunca se pode sacar mais do que o saldo) que nenhuma subclasse deve poder enfraquecer.
Um método private já é efetivamente final — não é visível para subclasses, portanto marcar um método privado como final é redundante (e o PHP 8 emite um aviso para final private, exceto no construtor).
Constantes finais (PHP 8.1+)
Antes do PHP 8.1, uma subclasse podia redefinir uma constante herdada. O PHP 8.1 adicionou final para constantes, permitindo que você evite isso:
<?php
class HttpStatus
{
final public const OK = 200;
}
class ApiStatus extends HttpStatus
{
// Fatal error: ApiStatus::OK cannot override final constant HttpStatus::OK
// public const OK = 201;
}Se você precisa de constantes que fazem parte de um contrato fixo — códigos de status, nomes de papel, chaves de configuração — final garante que toda subclasse as respeite. Saiba mais em constantes de classe.
Propriedades finais (PHP 8.4+)
Antes do PHP 8.4, final não podia ser aplicado a uma propriedade. O PHP 8.4 adicionou propriedades final: uma propriedade final ainda pode ser lida e escrita, mas uma subclasse não pode redeclará-la.
<?php
class Car
{
final public string $model = "Toyota";
}
class Toyota extends Car
{
// Fatal error: Cannot override final property Car::$model
// public string $model = "Corolla";
}Observe que final controla a redeclaração, não a mutabilidade — o valor ainda pode ser reatribuído em tempo de execução. Para tornar um valor imutável após a construção, use uma propriedade readonly; os dois modificadores são frequentemente combinados (final public readonly string $model). No PHP 8.3 e anteriores, marcar qualquer propriedade como final é um erro fatal.
final vs. abstract
final e abstract são opostos e não podem ser combinados:
abstractsignifica deve ser implementado por uma subclasse — requer herança.finalsignifica não pode ser estendido ou substituído — proíbe herança.
Declarar final abstract class é um erro fatal. Veja classes abstratas para o outro lado desta moeda.
Quando usar final
- Bloquear um invariante. Um método
finalgarante que a lógica crítica (validação, verificações de segurança, faturamento) não possa ser silenciosamente alterada mais adiante. - Sinalizar classes "concluídas". Uma classe
finalinforma aos leitores que o design é intencional e não se destina a ser subclassificado. - Preferir composição em vez de herança. Quando você prefere que os consumidores envolvam sua classe em vez de estendê-la,
finalos orienta nessa direção.
Um contra-argumento comum: final pode dificultar o teste ou a simulação do código, já que você não pode criar uma subclasse de uma classe final. A resposta moderna é depender de interfaces (de modo que você simule a interface, não a classe concreta) — veja interfaces. Recorra a final quando a restrição for genuinamente parte do design, não como um hábito indiscriminado.
Conclusão
A palavra-chave final fecha uma classe, método ou constante para modificação por subclasses, transformando uma intenção de design em uma regra imposta pelo compilador. Use-a em classes que estão completas, em métodos que protegem invariantes e em constantes que formam um contrato fixo — mas lembre-se de que não pode ser aplicada a propriedades e não pode ser combinada com abstract.