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.