PHP 8 - 枚舉介紹

他們終於即將到來 - 內置對枚舉的支持將在 php 8.1 中添加。

像往常一樣,使用我的PHP函數帖子,我們從高級概述開始,枚舉是什麼樣的:

enum Status
{
    case DRAFT;
    case PUBLISHED;
    case ARCHIVED;
}

枚舉的好處是它們代表了一個常量值的集合,但最重要的是可以輸入這些值,如:

class BlogPost
{
    public function __construct(
        public Status $status, 
    ) {}
}

在此示例中,創建枚舉並將其傳遞給 blogpost 如下所示:

$post = new BlogPost(Status::DRAFT);

這是基本的方式,因爲你可以看到沒有任何複雜的事情。

# 枚舉方法

枚舉可以定義方法,就像類一樣。這是一個非常強大的函數,特別是與 match 運算符配合使用:

enum Status
{
    case DRAFT;
    case PUBLISHED;
    case ARCHIVED;
    
    public function color(): string
    {
        return match($this) 
        {
            Status::DRAFT => 'grey',   
            Status::PUBLISHED => 'green',   
            Status::ARCHIVED => 'red',   
        };
    }
}

方法可以如此使用:

$status = Status::ARCHIVED;

$status->color(); // 'red'

允許靜態方法:

enum Status
{
    // …
    
    public static function make(): Status
    {
        // …
    }
}

您也可以使用 self :

enum Status
{
    // …
    
    public function color(): string
    {
        return match($this) 
        {
            self::DRAFT => 'grey',   
            self::PUBLISHED => 'green',   
            self::ARCHIVED => 'red',   
        };
    }
}

# 枚舉接口

枚舉可以實現接口,就像普通類一樣:

interface HasColor
{
    public function color(): string;
}
enum Status implements HasColor
{
    case DRAFT;
    case PUBLISHED;
    case ARCHIVED;
    
    public function color(): string { /* … */ }
}

# 枚舉值 

枚舉值由內部的對象表示,但如果您願意,可以爲它們分配一個值;

enum Status: string
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';
}

注意枚舉定義中的類型聲明。它表示所有枚舉值都是給定類型的。您也可以使其成爲 int 。請注意,僅 int  String 被允許作爲枚舉值。

enum Status: int
{
    case DRAFT = 1;
    case PUBLISHED = 2;
    case ARCHIVED = 3;
}

鍵入枚舉的技術術語被稱爲"backed enums",因爲它們被更簡單的值"backed"。如果您決定分配枚舉值,則所有情況都應具有值。

# 帶接口的枚舉

如果您要合併支持的枚舉和接口,則枚舉類型必須直接在枚舉名稱之後,在Implements關鍵字之前。

enum Status: string implements HasColor
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';
    
    // …
}

# 序列化枚舉

如果要爲enum分配值,則可能需要一種序列化和反序列化它們的方法。序列化意味着您需要一種訪問枚舉值的方法。這是通過只讀公共屬性完成的:

$value = Status::PUBLISHED->value; // 2

可以通過使用Enum::from

$status = Status::from(2); // Status::PUBLISHED

還有一個 tryfrom ,它返回 null 如果通過了未知值。如果您使用 from 將存在異常。

$status = Status::from('unknown'); // ValueError
$status = Status::tryFrom('unknown'); // null

請注意,您還可以對枚舉使用內置的序列化(serialize)和反序列化(unsermalize)功能。此外,您可以將json_encode與支持的枚舉結合使用,其結果將是枚舉值。可以通過實現JsonSerializable來覆蓋此行爲。

# Listing enum values

您可以使用靜態的 Enum::cases()方法獲取枚舉中所有可用值的列表:

Status::cases();

/* [
    Status::DRAFT, 
    Status::PUBLISHED, 
    Status::ARCHIVED
] */

請注意,此數組包含實際的枚舉對象:

array_map(
    fn(Status $status) => $status->color(), 
    Status::cases()
);

使用支持的枚舉時,數組鍵將包含枚舉值:

Status::cases();

/* [
    'draft' => Status::DRAFT, 
    'published' => Status::PUBLISHED, 
    'archived' => Status::ARCHIVED,
] */

# 枚舉對象

我已經提到枚舉值表示爲對象,實際上這些是單例對象。這意味着您可以與它們進行比較:

$statusA = Status::PENDING;
$statusB = Status::PENDING;
$statusC = Status::ARCHIVED;

$statusA === $statusB; // true
$statusA === $statusC; // false
$statusC instanceof Status; // true

# 枚舉作爲數組鍵

由於枚舉值實際上是對象,因此目前無法將它們用作數組鍵。以下將導致錯誤:

$list = [
    Status::DRAFT => 'draft',
    // …
];

這意味着您只能在SplObjectStorage和WeakMaps中將枚舉用作鍵。

# Traits

枚舉可以像類一樣使用特徵,但有更多限制。您不允許覆蓋內置的枚舉方法,並且它們不能包含類屬性-枚舉中禁止使用這些屬性。

# Reflection and attributes

正如預期的那樣,有幾個用於處理枚舉的反射類: Reflectionenum  ReflectenumunitCase  ReflecteneNumbackedCase 。還有一個新的 enum_exists 函數,它是它的名字所建議的。

 

鏈接:https://www.learnfk.com/article-php-enums
來源:Learnfk無涯私塾網

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章