PHP教程

PHP回退(Backed)枚举

一、简介

PHP回退(Backed)枚举是一种特殊类型的枚举,它与普通枚举不同之处在于,它的值存储在数组中而不是直接定义。这种枚举类型可以提高性能和内存利用率,因为它不需要为每个枚举常量分配内存空间。

二、示例

默认情况下枚举条目实现形式不是标量。 它们是纯粹的对象实例。 不过,很多时候也需要在数据库、数据存储对象中来回读写枚举条目。 因此,能够内置支持标量形式也很有用(更易序列化)。

按以下语法,定义标量形式的枚举:

<?php
enum Suit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
?>

由于有标量的条目回退(Backed)到一个更简单值,又叫回退条目(Backed Case), 包含所有回退条目的 Enum 又叫“回退 Enum”(Backed Enum), 回退 Enum 只能包含回退条目, 纯粹 Enum 只能包含纯粹条目。

回退枚举仅能回退到 int 或 string 里的一种类型, 且同时仅支持使用一种类型(就是说,不能联合 int|string)。 如果枚举为标量形式,所有的条目必须明确定义唯一的标量值。 无法自动生成标量(比如:连续的数字)。 回退条目必须是唯一的;两个回退条目不能有相同的标量。 然而,也可以用常量引用到条目,实际上是创建了个别名。 参见 枚举常量。

条目等同的值,必须是个字面量或它的表达式。 不能是常量和常量表达式。 换言之,允许 1 + 1, 不允许 1 + SOME_CONST。回退条目有个额外的只读属性 value, 它是定义时指定的值。

<?php
print Suit::Clubs->value;
// 输出 "C"
?>

为了确保 value 的只读性, 无法将变量传引用给它。 也就是说,以下会抛出错误:

<?php
$suit = Suit::Clubs;
$ref = &$suit->value;
// Error: Cannot acquire reference to property Suit::$value
?>

回退枚举实现了内置的 BackedEnum interface, 暴露了两个额外的方法:

  • from(int|string): self 能够根据标量返回对应的枚举条目。 如果找不到该值,会抛出 ValueError。 主要用于输入标量为可信的情况,使用一个不存在的枚举值,可以考虑为需终止应用的错误;
  • tryFrom(int|string): ?self 能够根据标量返回对应的枚举条目。 如果找不到该值,会返回 null。 主要用于输入标量不可信的情况,调用者需要自己实现默认值的逻辑或错误的处理。

from() 和 tryFrom() 方法也遵循基本的严格/松散类型规则。 系统在弱类型模式下接受传入 integer 和 string,并自动强制转换对应值。 传入 float 也能运行,并且强制转换。 在严格类型模式下,为 string 回退枚举的 from() 传入 integer 会导致 TypeError,反之亦然;float 都会出现有问题。 其他所有的参数类型,在以上所有模式中都会抛出 TypeError。

<?php
$record = get_stuff_from_database($id);
print $record['suit'];

$suit =  Suit::from($record['suit']);
// 无效数据抛出 ValueError:"X" is not a valid scalar value for enum "Suit"
print $suit->value;

$suit = Suit::tryFrom('A') ?? Suit::Spades;
// 无效数据返回 null,因此会用 Suit::Spades 代替。
print $suit->value;
?>

手动为回退枚举定义 from() 或 tryFrom() 方法会导致 fatal 错误。

广告合作
QQ群号:707632017

温馨提示:

1、本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。邮箱:2942802716#qq.com。(#改为@)

2、本站原创内容未经允许不得转裁,转载请注明出处“站长百科”和原文地址。

目录