PHP入門:列挙型(Enum)について -vol.2-

スポンサーリンク
PHP入門:列挙型(Enum)について -vol.2- 用語解説
PHP入門:列挙型(Enum)について -vol.2-
この記事は約6分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

今日は、PHPの列挙型(Enum)についてご紹介します。

スポンサーリンク

背景

PHP8.2を利用したAPIを開発しているときに列挙型(Enum)を利用したので、そのときの調査内容を備忘としてのこしました。

こちらのサイトを参考にしています。

列挙型(Enum)メソッド

列挙型(”Pure Enum”と”Backed Enum”の両方)はメソッドを含むことができ、インターフェースを実装することもできます。列挙型がインターフェースを実装する場合、そのインターフェースの型チェックはその列挙型のすべてのケースを受け入れます。

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

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

    // インターフェースの実装
    public function color(): string
    {
        return match($this) {
            Suit::Hearts, Suit::Diamonds => 'Red',
            Suit::Clubs, Suit::Spades => 'Black',
        };
    }

    // インターフェースの一部ではないが、問題ありません。
    public function shape(): string
    {
        return "Rectangle";
    }
}

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

paint(Suit::Clubs);  // 動作します

print Suit::Diamonds->shape(); // "Rectangle" を表示

この例では、Suitの4つのインスタンスは2つのメソッド、color() および shape() を持っています。呼び出しコードと型チェックに関しては、他のオブジェクトインスタンスとまったく同じように動作します。

バックアッド列挙型では、インターフェース宣言はバックアッドタイプ宣言の後に続きます。

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

enum Suit: string implements Colorful
{
    case Hearts = 'H';
    case Diamonds = 'D';
    case Clubs = 'C';
    case Spades = 'S';

    // インターフェースの実装
    public function color(): string
    {
        return match($this) {
            Suit::Hearts, Suit::Diamonds => 'Red',
            Suit::Clubs, Suit::Spades => 'Black',
        };
    }
}

メソッド内では、$this 変数が定義され、ケースインスタンスを参照します。メソッドは任意の複雑さを持つことができますが、実際には通常、静的な値を返したり、 $this に対してマッチングして異なるケースに異なる結果を提供します。

ただし、この場合、より良いデータモデリングの実践として、SuitColor Enum型を定義し、その値を返す方が良いです。ただし、この例を複雑にすることになります。

上記の階層は、論理的には次のクラス構造に似ています(これは実際の実行コードではありません):

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

final class Suit implements UnitEnum, Colorful
{
    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::Hearts, Suit::Diamonds => 'Red',
            Suit::Clubs, Suit::Spades => 'Black',
        };
    }

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

    public static function cases(): array
    {
        // 手動で列挙型の cases() メソッドを定義することは許可されていません。
        // "値一覧" セクションも参照してください。
    }
}

メソッドは public、private、または protected にすることができますが、実際のところ private と protected は継承が許可されていないため、同等です。

列挙型(Enum)静的メソッド

列挙型(Enum)は静的メソッドも持つことができます。列挙型自体の静的メソッドの主な用途は、代替コンストラクタです。たとえば:

enum Size
{
    case Small;
    case Medium;
    case Large;

    public static function fromLength(int $cm): static
    {
        return match(true) {
            $cm < 50 => static::Small,
            $cm < 100 => static::Medium,
            default => static::Large,
        };
    }
}

静的メソッドは public、private、または protected にすることができますが、実際のところ private と protected は継承が許可されていないため、同等です。このような静的メソッドは、列挙型内で新しいインスタンスを作成したり、特定の条件に基づいて既存の列挙型のケースを返したりする際に便利です。

おわりに

今日は、PHPの列挙型(Enum)についてご紹介しました。

よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました