2

PHP8.1之enum解析

 2 years ago
source link: https://segmentfault.com/a/1190000041091095
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

PHP8.1之enum解析

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 的一个实例。tryFromfrom 的区别在于如果传递一个不存在的值,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: fromtryFrom 方法是不能被重写的.

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'));
  1. 因为 enum 本质上还是一个类,所以有些普通类的函数,enum 也能用,比如 instanceof.
<?php

var_dump(Week::Monday instanceof Week);
  1. 使用 ::class 返回完全限定名,同样适用于 enum 类型.
  2. 命名空间也基本和类一致.
  3. 定义字符串,也可以用 heredoc 语法.
<?php

enum Week: string {
    const Monday = <<<MONDAY
This is monday.
MONDAY;
}

ENUM和普通类的对比

ENUM普通类构造函数不支持支持析构函数不支持支持序列化函数不支持支持反序列化函数不支持支持克隆函数不支持支持类属性不支持支持动态属性不支持支持用 new 实例化不支持支持

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK