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

列挙型の 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
}

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

$foo = new Foo();
?>