2024 PHP 日本大会

为什么枚举不可扩展

类对其方法有约定

<?php

class A {}
class
B extends A {}

function
foo(A $a) {}

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

这段代码是类型安全的,因为 B 遵循 A 的约定,并且通过协变/逆变的机制,对方法的任何预期都将被保留,异常除外。

枚举对其情况下有约定,而不是方法

<?php

enum ErrorCode {
case
SOMETHING_BROKE;
}

function
quux(ErrorCode $errorCode)
{
// 编写时,这段代码似乎涵盖了所有情况
match ($errorCode) {
ErrorCode::SOMETHING_BROKE => true,
}
}

?>

函数 quux 中的 match 语句可以通过静态分析来验证其是否涵盖了 ErrorCode 中的所有情况。

但想象一下,如果允许扩展枚举会怎样

<?php

// 假设枚举不是 final 的代码示例。
// 注意,这在 PHP 中实际上无法运行。
enum MoreErrorCode extends ErrorCode {
case
PEBKAC;
}

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

fot(MoreErrorCode::PEBKAC);

?>

在正常的继承规则下,扩展另一个类的类将通过类型检查。

quux() 中的 match 语句不再涵盖所有情况。因为它不知道 MoreErrorCode::PEBKAC,所以 match 将抛出异常。

因此,枚举是 final 的,不能扩展。

添加注释

用户贡献的注释

此页面没有用户贡献的注释。
To Top