PHP8 为什么枚举不可扩展

2023-08-19 16:08 更新

类在方法有契约:

<?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)
{
// When written, this code appears to cover all cases
match ($errorCode) {
ErrorCode::SOMETHING_BROKE => true,
}
}

?>

在函数 quux 中,match 语句可以进行静态分析,以涵盖 ErrorCode 中的所有情况。

但是想一下,如果允许扩展枚举:

<?php
// Thought experiment code where enums are not final.
// Note, this won't actually work in PHP.
enum MoreErrorCode extends ErrorCode {
case PEBKAC;
}

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

fot(MoreErrorCode::PEBKAC);

?>

根据正常的继承规则,继承另一个类的类将通过类型检查。

问题在于 quux() 中的 match 语句不再涵盖所有情况。因为它不知道 MoreErrorCode::PEBKAC,所以匹配语句会抛出异常。

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


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号