W3docs

final

La palabra clave "final" en PHP permite marcar clases, métodos o propiedades como finales, impidiendo que sean sobreescritos por subclases.

La palabra clave final de PHP

final es una palabra clave de programación orientada a objetos en PHP que bloquea una parte de una clase para que las subclases no puedan modificarla. Puedes aplicarla a una clase (ninguna otra clase puede extenderla), a un método (ninguna subclase puede sobreescribirlo) o, desde PHP 8.1, a una constante (ninguna subclase puede redefinirla).

Marcar algo como final es una declaración de diseño deliberada: "este comportamiento es intencional y las clases hijas no deben alterarlo." Bien utilizado, previene sobreescrituras accidentales, documenta la intención en el código y te permite razonar sobre una clase sin preocuparte de que una subclase haya cambiado silenciosamente su funcionamiento. Esta página cubre cada forma de final, cuándo usarlo y los errores comunes que suelen cometerse.

¿Ya tienes experiencia con subclases y sobreescritura? final solo tiene sentido en el contexto de herencia en PHP y clases y objetos.

Clases finales

Una clase final no puede ser extendida. Cualquier intento de declarar una subclase produce un error fatal en tiempo de compilación:

<?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 {}

Usa una clase final cuando su comportamiento está completo y la herencia sería un uso incorrecto — por ejemplo, un objeto de valor, un servicio cuyo contrato controlas tú, o una clase sensible a la seguridad donde una subclase que sobreescriba podría saltarse una verificación.

Métodos finales

Puedes mantener una clase extensible pero bloquear métodos individuales. Un método final puede ser heredado y llamado por subclases, pero no puede ser sobreescrito:

<?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 es el uso más común de final: quieres que una clase sea abierta para extensión en general, pero un método específico impone una invariante (aquí, nunca se puede retirar más del saldo disponible) que ninguna subclase debería poder debilitar.

"Pruébalo tú mismo" no está disponible para este ejemplo.

Un método private ya es efectivamente final — no es visible para las subclases, por lo que marcar un método privado como final es redundante (y PHP 8 emite una advertencia para final private, excepto en el constructor).

Constantes finales (PHP 8.1+)

Antes de PHP 8.1, una subclase podía redefinir una constante heredada. PHP 8.1 añadió final para constantes, lo que permite evitar eso:

<?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;
}

Si necesitas constantes que formen parte de un contrato fijo — códigos de estado, nombres de roles, claves de configuración — final mantiene la coherencia en todas las subclases. Aprende más en constantes de clase.

Propiedades finales (PHP 8.4+)

Antes de PHP 8.4, final no podía aplicarse a una propiedad. PHP 8.4 añadió propiedades final: una propiedad final puede seguir siendo leída y escrita, pero una subclase no puede redeclararla.

<?php

class Car
{
    final public string $model = "Toyota";
}

class Toyota extends Car
{
    // Fatal error: Cannot override final property Car::$model
    // public string $model = "Corolla";
}

Ten en cuenta que final controla la redeclaración, no la mutabilidad — el valor puede seguir reasignándose en tiempo de ejecución. Para hacer que un valor sea inmutable tras la construcción, usa una propiedad readonly; los dos modificadores se combinan frecuentemente (final public readonly string $model). En PHP 8.3 y versiones anteriores, marcar cualquier propiedad como final es un error fatal.

final vs. abstract

final y abstract son opuestos y no pueden combinarse:

  • abstract significa que debe ser implementado por una subclase — exige herencia.
  • final significa que no puede ser extendido ni sobreescrito — prohíbe la herencia.

Declarar final abstract class es un error fatal. Consulta clases abstractas para ver la otra cara de esta moneda.

Cuándo usar final

  • Bloquear una invariante. Un método final garantiza que la lógica crítica (validación, controles de seguridad, facturación) no pueda ser modificada silenciosamente aguas abajo.
  • Indicar clases "terminadas". Una clase final les dice a los lectores que el diseño es intencional y no está pensado para ser subclasificado.
  • Preferir composición sobre herencia. Cuando prefieres que los consumidores envuelvan tu clase en lugar de extenderla, final los orienta en esa dirección.

Un argumento contrario común: final puede dificultar las pruebas o el uso de mocks, ya que no puedes subclasificar una clase final. La respuesta moderna es depender de interfaces (de modo que hagas mock de la interfaz, no de la clase concreta) — consulta interfaces. Recurre a final cuando la restricción sea genuinamente parte del diseño, no como un hábito general.

Conclusión

La palabra clave final cierra una clase, método o constante a la modificación por parte de subclases, convirtiendo una intención de diseño en una regla impuesta por el compilador. Úsala en clases que estén completas, en métodos que protejan invariantes y en constantes que formen un contrato fijo — pero recuerda que no puede aplicarse a propiedades y no puede combinarse con abstract.

Práctica

Práctica
¿Qué indica la palabra clave 'final' en PHP?
¿Qué indica la palabra clave 'final' en PHP?
Was this page helpful?