## 定数式における列挙型の値

列挙型の case は、定数として表現されているので、 ほとんどの定数式の中で静的な値として使えます。 つまり、プロパティのデフォルト値や、 static 変数のデフォルト値、パラメータのデフォルト値、 グローバル定数やクラス定数の値として使えます。 列挙型の case 以外の値は使えませんが、 通常の定数は、列挙型の case を参照できます。

しかしながら、列挙型の中で ArrayAccess のような暗黙のマジックメソッドの呼び出しを行うことは、 定数や static な定義では許されません。 なぜなら、結果の値が保証できなくなりますし、 副作用がまったくないことも保証できないからです。 関数コールやメソッドコール、そしてプロパティへのアクセスは、 引き続き定数式では不正な操作として扱われます。

    <?php

    // これは、完全に正しい列挙型の定義です
    enum Direction implements ArrayAccess
    {
        case Up;
        case Down;

        public function offsetExists($offset): bool
        {
            return false;
        }

        public function offsetGet($offset): mixed
        {
            return null;
        }

        public function offsetSet($offset, $value): void
        {
            throw new Exception();
        }

        public function offsetUnset($offset): void
        {
            throw new Exception();
        }
    }

    class Foo
    {
        // これは、許されています。
        const DOWN = Direction::Down;

        // これは、許可されません。結果の値が保証できない可能性があります。
        const UP = Direction::Up['short'];
        // Fatal error: Cannot use [] on enums in constant expression
    }

    // これは、完全に正しいコードです。定数式ではないからです。
    $x = Direction::Up['short'];
    var_dump("\$x is " . var_export($x, true));

    $foo = new Foo();

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open