PHP8.1釋出了, 一個 enum 就有好多東西要注意.
enum
基本上就是一個限定類, 先看看它的語法結構是什麼樣的.
enum_declaration_statement:
T_ENUM { $<num>$ = CG(zend_lineno); }
T_STRING enum_backing_type implements_list backup_doc_comment '{' class_statement_list '}'
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_ENUM|ZEND_ACC_FINAL, $<num>2, $6, zend_ast_get_str($3), NULL, $5, $8, NULL, $4); }
;
enum
關鍵字打頭, 後面可選跟: (string|int)
, 因為是類所以可以實現介面 implement SomeInterface, MoreInterface
, 又因為加了 ZEND_ACC_FINAL
, 相當於 final class className
, 所以是不能繼承別的列舉型別.
定義
<?php
//不初始化值,直接這樣定義是可以的
enum Week {
case Monday;
}
//這樣是錯誤的,裡面的列舉元素初始化值,必須指定整個列舉型別的變數型別,string 或者 int
enum Week {
case Monday = 'monday';
}
//正確的方式
enum Week: string {
case Monday = 'monday';
}
enum的一些特定操作
<?php
enum Week: string {
case Monday = 'monday';
case Tuesday = 'tuesday';
}
//獲取列舉型別元素的值
echo Week::Monday->value;
//獲取列舉型別元素的key
echo Week::Monday->name;
Week::Monday
就是這個列舉型別的一個例項,相當於普通類的 object
.
注意列舉型別不能被例項化
,也沒有構造和解構函式。如果用new
去例項化Week
,會得到一個fatal error
.
通過值獲取例項
enum Week: string {
case Monday = 'monday';
case Tuesday = 'tuesday';
}
var_dump(Week::from('monday'));
var_dump(Week::tryFrom('money'));
Week::from
返回的是 Worker::Monday
,是 Week
的一個例項。tryFrom
跟 from
的區別在於如果傳遞一個不存在的值,form
會報錯,而 tryFrom
返回的是 null
.
tryFrom
配合新語法,程式碼會更加精簡.
//不使用 tryFrom
try {
$value = Week::from('no_exists_value')->value;
} catch (Throwable $e) {
$value = null;
}
//使用 tryFrom 加新語法
$value = Week::tryFrom('no_exists_value')?->value;
tips:from
和tryFrom
方法是不能被重寫的.
enum 定義方法
enum Week: string {
case Monday = 'monday';
case Tuesday = 'tuesday';
public function test() {
echo 'test'. PHP_EOL;
}
}
Week::Monday->test();
呼叫和普通類一樣,例項->方法名,所以只要牢記 Week::Monday
返回的是例項,其它操作跟類高度相似。
enum 實現介面
<?php
interface TestInterface {
public function test();
}
interface MultiInterface {
public function func();
}
enum Week: string implements TestInterface, MultiInterface {
case Monday = 'monday';
case Tuesday = 'tuesday';
public function test() {
echo 'test'. PHP_EOL;
}
public function func() {
echo 'multi interface func'. PHP_EOL;
}
}
enum使用trait
trait Testable {
public function test() {
echo 'test'.PHP_EOL;
}
}
enum Week: string {
use Testable;
case Monday = 'monday';
case Tuesday = 'tuesday';
}
enum 獲取例項列表
<?php
enum Week: string {
case Monday = 'monday';
case Tuesday = 'tuesday';
}
var_dump(Week::cases());
tips: cases
方法也不能被重寫.
判斷一個 enum 是否存在
<?php
enum Week: string {
case Monday = 'monday';
case Tuesday = 'tuesday';
}
var_dump(enum_exists('Week'));
其它
- 因為
enum
本質上還是一個類,所以有些普通類的函式,enum
也能用,比如instanceof
.
<?php
var_dump(Week::Monday instanceof Week);
- 使用
::class
返回完全限定名,同樣適用於enum
型別. - 名稱空間也基本和類一致.
- 定義字串,也可以用
heredoc
語法.
<?php
enum Week: string {
const Monday = <<<MONDAY
This is monday.
MONDAY;
}
ENUM和普通類的對比
ENUM | 普通類 | |
---|---|---|
建構函式 | 不支援 | 支援 |
解構函式 | 不支援 | 支援 |
序列化函式 | 不支援 | 支援 |
反序列化函式 | 不支援 | 支援 |
克隆函式 | 不支援 | 支援 |
類屬性 | 不支援 | 支援 |
動態屬性 | 不支援 | 支援 |
用 new 例項化 | 不支援 | 支援 |