W3docs

final

Le mot-clé "final" en PHP empêche les sous-classes de modifier une classe, une méthode ou une constante héritée.

Le mot-clé final en PHP

final est un mot-clé de la programmation orientée objet en PHP qui verrouille une partie d'une classe afin que les sous-classes ne puissent pas la modifier. Vous pouvez l'appliquer à une classe (aucune autre classe ne peut l'étendre), à une méthode (aucune sous-classe ne peut la redéfinir) ou, depuis PHP 8.1, à une constante (aucune sous-classe ne peut la redéclarer).

Marquer quelque chose comme final est une décision de conception délibérée : « ce comportement est intentionnel, et les classes enfants ne doivent pas le modifier. » Bien utilisé, cela prévient les redéfinitions accidentelles, documente l'intention dans le code et vous permet de raisonner sur une classe sans vous demander si une sous-classe en a silencieusement modifié le fonctionnement. Cette page couvre chaque forme de final, quand y recourir, et les pièges courants.

Déjà à l'aise avec les sous-classes et la redéfinition ? final n'a de sens que dans le contexte de l'héritage PHP et des classes et objets.

Classes finales

Une classe final ne peut pas être étendue. Toute tentative de déclarer une sous-classe provoque une erreur fatale à la compilation :

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

Utilisez une classe finale lorsque son comportement est complet et que l'héritage serait un usage abusif — par exemple un objet valeur, un service dont vous contrôlez le contrat, ou une classe sensible à la sécurité où une sous-classe de remplacement pourrait contourner une vérification.

Méthodes finales

Vous pouvez garder une classe extensible tout en verrouillant certaines méthodes individuellement. Une méthode final peut être héritée et appelée par des sous-classes, mais elle ne peut pas être redéfinie :

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

C'est l'utilisation la plus courante de final : vous souhaitez qu'une classe soit ouverte à l'extension en général, mais une méthode spécifique impose un invariant (ici, il est impossible de retirer plus que le solde disponible) qu'aucune sous-classe ne doit pouvoir affaiblir.

« Essayez vous-même » n'est pas disponible pour cet exemple.

Une méthode private est déjà effectivement finale — elle n'est pas visible des sous-classes, donc marquer une méthode privée comme final est redondant (et PHP 8 émet un avertissement pour final private, sauf sur le constructeur).

Constantes finales (PHP 8.1+)

Avant PHP 8.1, une sous-classe pouvait redéfinir une constante héritée. PHP 8.1 a introduit final pour les constantes afin de l'empêcher :

<?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 vous avez besoin de constantes faisant partie d'un contrat fixe — codes de statut, noms de rôles, clés de configuration — final garantit la cohérence dans toutes les sous-classes. En savoir plus dans les constantes de classe.

Propriétés finales (PHP 8.4+)

Avant PHP 8.4, final ne pouvait pas être appliqué à une propriété. PHP 8.4 a introduit les propriétés final : une propriété final peut toujours être lue et écrite, mais une sous-classe ne peut pas la redéclarer.

<?php

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

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

Notez que final contrôle la redéclaration, pas la mutabilité — la valeur peut encore être réassignée à l'exécution. Pour rendre une valeur immuable après la construction, utilisez une propriété readonly ; les deux modificateurs sont souvent combinés (final public readonly string $model). Sur PHP 8.3 et antérieur, marquer une propriété comme final est une erreur fatale.

final vs. abstract

final et abstract sont opposés et ne peuvent pas être combinés :

  • abstract signifie doit être implémenté par une sous-classe — il exige l'héritage.
  • final signifie ne peut pas être étendu ou redéfini — il interdit l'héritage.

Déclarer final abstract class est une erreur fatale. Voir les classes abstraites pour l'autre côté de cette médaille.

Quand utiliser final

  • Verrouiller un invariant. Une méthode final garantit que la logique critique (validation, vérifications de sécurité, facturation) ne peut pas être silencieusement modifiée en aval.
  • Signaler les classes « terminées ». Une classe final indique aux lecteurs que la conception est intentionnelle et qu'elle n'est pas destinée à être sous-classée.
  • Privilégier la composition à l'héritage. Lorsque vous préférez que les consommateurs enveloppent votre classe plutôt que de l'étendre, final les oriente dans cette direction.

Un contre-argument courant : final peut rendre le code plus difficile à tester ou à simuler, puisqu'on ne peut pas sous-classer une classe finale. La réponse moderne est de dépendre d'interfaces (pour simuler l'interface, et non la classe concrète) — voir les interfaces. Recourez à final quand la contrainte fait genuinement partie de la conception, et non comme une habitude systématique.

Conclusion

Le mot-clé final ferme une classe, une méthode ou une constante à la modification par les sous-classes, transformant une intention de conception en règle imposée par le compilateur. Utilisez-le sur les classes complètes, sur les méthodes qui protègent des invariants, et sur les constantes qui forment un contrat fixe — mais rappelez-vous qu'il ne peut pas être appliqué aux propriétés et ne peut pas être combiné avec abstract.

Pratique

Pratique
Que désigne le mot-clé 'final' en PHP ?
Que désigne le mot-clé 'final' en PHP ?
Was this page helpful?