## Pourquoi les enums ne sont pas extensibles

Les classes ont des contrats sur leurs méthodes :

    <?php

    class A {}
    class B extends A {}

    function foo(A $a) {}

    function bar(B $b)
    {
        foo($b);
    }

Ce code est sûr du point de vue du type, car B suit le contrat de A, et par la magie de la co/contra-variance, toute attente que l'on peut avoir à l'égard des méthodes sera préservée, sauf exceptions.

Les enums ont des contrats sur leurs cas, pas sur les méthodes :

    <?php

    enum ErrorCode
    {
        case SOMETHING_BROKE;
    }

    function quux(ErrorCode $errorCode)
    {
        // Quand écrit, ce code semble couvrir tous les cas de figure
        match ($errorCode) {
            ErrorCode::SOMETHING_BROKE => true,
        };
    }

L'instruction match dans la fonction `quux` peut être analysée statiquement pour couvrir tous les cas d'ErrorCode.

Mais imaginons qu'il soit permis d'étendre les enums :

    <?php

    // Code d'expérience de pensée où les enums ne sont pas finaux.
    // À noter : cela ne fonctionnera pas en PHP.
    enum MoreErrorCode extends ErrorCode
    {
        case PEBKAC;
    }

    function fot(MoreErrorCode $errorCode)
    {
        quux($errorCode);
    }

    fot(MoreErrorCode::PEBKAC);

En vertu des règles d'héritage normales, une classe qui en étend une autre passera le contrôle de type.

Le problème serait que l'instruction match dans `quux()` ne couvre plus tous les cas. Parce qu'elle ne connaît pas `MoreErrorCode::PEBKAC`, la correspondance lèvera une exception.

Pour cette raison, les enums sont finaux et ne peuvent pas être étendus.

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open