枚舉方法

枚舉(包括純粹枚舉、回退枚舉)還能包含方法, 也能實現(xiàn) interface。 如果 Enum 實現(xiàn)了 interface,則其中的條目也能接受 interface 的類型檢測。

<?php
interface Colorful
{
    public function 
color(): string;
}

enum Suit implements Colorful
{
    case 
Hearts;
    case 
Diamonds;
    case 
Clubs;
    case 
Spades;

    
// 滿足 interface 契約。
    
public function color(): string
    
{
        return 
match($this) {
            
Suit::HeartsSuit::Diamonds => 'Red',
            
Suit::ClubsSuit::Spades => 'Black',
        };
    }

    
// 不是 interface 的一部分;也沒問題
    
public function shape(): string
    
{
        return 
"Rectangle";
    }
}

function 
paint(Colorful $c) { ... }

paint(Suit::Clubs);  // 正常

print Suit::Diamonds->shape(); // 輸出 "Rectangle"
?>

在這例子中,Suit 所有的四個實例具有兩個方法: color()、shape()。 目前的調(diào)用代碼和類型檢查,和其他對象實例的行為完全一致。

在回退枚舉中,interface 的聲明緊跟回退類型的聲明之后。

<?php
interface Colorful
{
    public function 
color(): string;
}

enum Suitstring implements Colorful
{
    case 
Hearts 'H';
    case 
Diamonds 'D';
    case 
Clubs 'C';
    case 
Spades 'S';

    
// 滿足 interface 的契約。
    
public function color(): string
    
{
        return 
match($this) {
            
Suit::HeartsSuit::Diamonds => 'Red',
            
Suit::ClubsSuit::Spades => 'Black',
        };
    }
}
?>

在方法中,定義了 $this 變量,它引用到了條目實例。

方法中可以任意復雜,但一般的實踐中,往往會返回靜態(tài)的值, 或者為 $this match 各種情況并返回不同的值。

注意,在本示例中,更好的數(shù)據(jù)模型實踐是再定一個包含 Red 和 Black 枚舉值的 SuitColor 枚舉,并且返回它作為代替。 然而這會讓本示例復雜化。

以上的層次在邏輯中類似于下面的 class 結(jié)構(gòu)(雖然這不是它實際運行的代碼):

<?php
interface Colorful
{
    public function 
color(): string;
}

final class 
Suit implements UnitEnumColorful
{
    public const 
Hearts = new self('Hearts');
    public const 
Diamonds = new self('Diamonds');
    public const 
Clubs = new self('Clubs');
    public const 
Spades = new self('Spades');

    private function 
__construct(public readonly string $name) {}

    public function 
color(): string
    
{
        return 
match($this) {
            
Suit::HeartsSuit::Diamonds => 'Red',
            
Suit::ClubsSuit::Spades => 'Black',
        };
    }

    public function 
shape(): string
    
{
        return 
"Rectangle";
    }

    public static function 
cases(): array
    {
        
// 不合法的方法,Enum 中不允許手動定義 cases() 方法
        // 參考 “枚舉值清單” 章節(jié)
    
}
}
?>

僅管 enum 可以包括 public、private、protected 的方法, 但由于它不支持繼承,因此在實踐中 private 和 protected 效果是相同的。