默認情況下枚舉條目實(shí)現形式不是標量。 它們是純粹的對象實(shí)例。 不過(guò),很多時(shí)候也需要在數據庫、數據存儲對象中來(lái)回讀寫(xiě)枚舉條目。 因此,能夠內置支持標量形式也很有用(更易序列化)。
按以下語(yǔ)法,定義標量形式的枚舉:
<?php
enum Suit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
?>
由于有標量的條目回退(Backed)到一個(gè)更簡(jiǎn)單值,又叫回退條目(Backed Case)。 包含所有回退條目的 Enum 又叫“回退 Enum”(Backed Enum)。 回退 Enum 只能包含回退條目。 純粹 Enum 只能包含純粹條目。
回退枚舉僅能回退到 int
或 string
里的一種類(lèi)型,
且同時(shí)僅支持使用一種類(lèi)型(就是說(shuō),不能聯(lián)合 int|string
)。
如果枚舉為標量形式,所有的條目必須明確定義唯一的標量值。
無(wú)法自動(dòng)生成標量(比如:連續的數字)。
回退條目必須是唯一的;兩個(gè)回退條目不能有相同的標量。
然而,也可以用常量引用到條目,實(shí)際上是創(chuàng )建了個(gè)別名。
參見(jiàn) 枚舉常量。
條目等同的值,必須是個(gè)字面量或它的表達式。
不能是常量和常量表達式。
換言之,允許 1 + 1
,
不允許 1 + SOME_CONST
。
回退條目有個(gè)額外的只讀屬性 value
,
它是定義時(shí)指定的值。
<?php
print Suit::Clubs->value;
// 輸出 "C"
?>
為了確保 value
的只讀性,
無(wú)法將變量傳引用給它。
也就是說(shuō),以下會(huì )拋出錯誤:
<?php
$suit = Suit::Clubs;
$ref = &$suit->value;
// Error: Cannot acquire reference to property Suit::$value
?>
回退枚舉實(shí)現了內置的 BackedEnum interface, 暴露了兩個(gè)額外的方法:
from(int|string): self
能夠根據標量返回對應的枚舉條目。
如果找不到該值,會(huì )拋出 ValueError。
主要用于輸入標量為可信的情況,使用一個(gè)不存在的枚舉值,可以考慮為需終止應用的錯誤。
tryFrom(int|string): ?self
能夠根據標量返回對應的枚舉條目。
如果找不到該值,會(huì )返回 null
。
主要用于輸入標量不可信的情況,調用者需要自己實(shí)現默認值的邏輯或錯誤的處理。
from()
和 tryFrom()
方法也遵循基本的嚴格/松散類(lèi)型規則。
系統在弱類(lèi)型模式下接受傳入 integer 和 string,并自動(dòng)強制轉換對應值。
傳入 float 也能運行,并且強制轉換。
在嚴格類(lèi)型模式下,為 string 回退枚舉的 from()
傳入 integer 會(huì )導致
TypeError,反之亦然;float 都會(huì )出現有問(wèn)題。
其他所有的參數類(lèi)型,在以上所有模式中都會(huì )拋出 TypeError。
<?php
$record = get_stuff_from_database($id);
print $record['suit'];
$suit = Suit::from($record['suit']);
// 無(wú)效數據拋出 ValueError:"X" is not a valid scalar value for enum "Suit"
print $suit->value;
$suit = Suit::tryFrom('A') ?? Suit::Spades;
// 無(wú)效數據返回 null,因此會(huì )用 Suit::Spades 代替。
print $suit->value;
?>
手動(dòng)為回退枚舉定義 from()
或 tryFrom()
方法會(huì )導致 fatal 錯誤。