PHP.nl

Why enums aren't extendable

Waarom enums niet uitbreidbaar zijn

Klassen hebben contracten voor hun methoden:

<?php

class A {}
class B extends A {}

function foo(A $a) {}

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

Deze code is type-veilig, aangezien B het contract van A volgt, en door de magie van co/contra-variantie, zullen alle verwachtingen die men heeft van de methoden behouden blijven, met uitzondering van uitzonderingen.

Enums hebben contracten voor hun cases, niet voor methoden:

<?php

enum ErrorCode {
    case SOMETHING_BROKE;
}

function quux(ErrorCode $errorCode)
{
    // Wanneer geschreven, lijkt deze code alle cases te dekken
    match ($errorCode) {
        ErrorCode::SOMETHING_BROKE => true,
    };
}

?>

De match-instructie in de functie kan statisch worden geanalyseerd om alle cases in ErrorCode te dekken.
quux

Maar stel je voor dat het toegestaan was om enums uit te breiden:

<?php

// Denkexperimentcode waar enums niet final zijn.
// Let op, dit zal in PHP niet daadwerkelijk werken.
enum MoreErrorCode extends ErrorCode {
    case PEBKAC;
}

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

fot(MoreErrorCode::PEBKAC);

?>

Volgens de normale erfgoedregels zal een klasse die een andere uitbreidt de typecontrole doorstaan.

Het probleem zou zijn dat de match-instructie niet langer alle cases dekt. Omdat het niet weet over de match, zal het een uitzondering gooien.
quux()``MoreErrorCode::PEBKAC

Om deze reden zijn enums final en kunnen ze niet worden uitgebreid.

Documentatie