Las clases tienen contratos en sus métodos:
<?php
class A {}
class B extends A {}
function foo(A $a) {}
function bar(B $b) {
foo($b);
}
?>
Este código es seguro en cuanto a tipos, ya que B sigue el contrato de A, y a través de la magia de la co/contravariancia, cualquier expectativa que uno pueda tener de los métodos será preservada, exceptuando las excepciones.
Las enumeraciones tienen contratos en sus casos, no en sus métodos:
<?php
enum ErrorCode {
case SOMETHING_BROKE;
}
function quux(ErrorCode $errorCode)
{
// Cuando se escribe, este código parece cubrir todos los casos
match ($errorCode) {
ErrorCode::SOMETHING_BROKE => true,
};
}
?>
La sentencia match en la función quux
puede ser analizada estáticamente para cubrir
todos los casos en ErrorCode.
Pero imagina que estuviera permitido extender enumeraciones:
<?php
// Código de experimento mental donde las enumeraciones no son finales.
// Nota: esto no funcionará realmente en PHP.
enum MoreErrorCode extends ErrorCode {
case PEBKAC;
}
function fot(MoreErrorCode $errorCode) {
quux($errorCode);
}
fot(MoreErrorCode::PEBKAC);
?>
Bajo las reglas normales de herencia, una clase que extiende a otra pasará la comprobación de tipo.
El problema sería que la sentencia match en quux()
ya no cubriría todos
los casos. Debido a que no sabe acerca de MoreErrorCode::PEBKAC
, el match lanzará una excepción.
Debido a esto, las enumeraciones son finales y no pueden ser extendidas.