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 co/contra-varianza, cualquier expectativa que uno pueda tener de los métodos se mantendrá, expecto excepciones.
Enums tienen contratos en sus casos, no en sus métodos:
<?php
enum ErrorCode {
case SOMETHING_BROKE;
}
function quux(ErrorCode $errorCode)
{
// Cuando escribimos, 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.
But imagine it was allowed to extend enums:
<?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 reglas de herencia normales, una clase que extiende otra pasará la comprobación de tipo.
El problema sería que la sentencia match en quux()
ya no cubre todos
los casos. Porque no sabe sobre MoreErrorCode::PEBKAC
la sentencia match lanzará una excepción.
Por esta razón, las enumeraciónes son finales y no pueden ser extendidas.