ツイート
シェア
LINEで送る
B! はてぶでブックマーク
Pocketでブックマーク
RSSフィード

PHP8.1, Enum(列挙型)の追加。定数専用のクラス。

php
イラストダウンロードサイト【イラストAC】
の画像をもとに加工しています。

PHP8.1から列挙型が追加されました。Enumという特殊なクラスです。

列挙型は定数をまとめたもの。Javaにはすでにあるんですが、そのPHP版といったところです。

既存のクラスで同じことができなくもないんですが、定数の集合を明示することで読みやすくなります。

定数値をもたない定数が定義できる

Enumは特殊なクラスです。classキーワードの代わりに enum を使います。

enum Color
{
    case Red;
    case Green;
    case Blue;
    case Yellow;
    case White;
    case Black;
}

定数値が不要で定数名だけで定義できます。

これは便利。たんに区別するための定数だけが必要で値はどうでもいいなんてことはよくあります。

(定数名を値に入れたり。)

Enumは定数値がなくてもいいので使い勝手が良さそう。

Enumはシングルトンクラス

Enumはシングルトンなので1つのインスタンスしか持てません。各定数を参照するときは "::" を使います。

$val = Color::Red;
var_dump($val);
実行結果
enum(Color::Red)

ただし、enum自体のオブジェクト(Color)は参照できません。(変数に代入できない。)

$val = Color;
実行結果
PHP Fatal error:  Uncaught Error: Undefined constant "Color" in /home/vagrant/enum.php:14

caseの定数もクラスオブジェクト

caseキーワードで定義する定数もクラスです。caseオブジェクトは nameプロパティをもち、定数名を取得することも可能。

$val = Color::Red;
var_dump($val->name);
実行結果
string(3) "Red"

'->' を見ても分かるように、caseクラスはインスタンスなので、Enumクラスとちがって変数に代入するできます。

定数の比較

厳密な比較演算子(===, !==)で定数の比較ができます。

$val = Color::Red;
if (Color::Red === $val ) {
    var_dump(true);
} else {
    var_dump(false);
}

$val = Color::Yellow;
if (Color::Red !== $val ) {
    var_dump(true);
} else {
    var_dump(false);
}
bool(true)
bool(true)

instanceof 演算子はちょっと複雑で、caseオブジェクトは使えません。

$val = Color::Red;
if ( $val instanceof Color::Red ) {
    var_dump(true);
} else {
    var_dump(false);
}
実行結果
PHP Parse error:  syntax error, unexpected identifier "Red", expecting variable or "$" in /home/vagrant/enum.php on line 14

ただし、enumオブジェクトは可能。

$val = Color::Red;
if ( $val instanceof Color ) {
    var_dump(true);
} else {
    var_dump(false);
}

$val = Color::White;
if ( $val instanceof Color ) {
    var_dump(true);
} else {
    var_dump(false);
}
実行結果
bool(true)
bool(true)

enum自体のクラスはデータ型に使えるけどcaseクラスは使えません。

instanceofは、どのEnumを使ってるか? には使えるけど、定数比較では使えません。

結果を見る限り、caseクラスは、enumクラスの子クラスのようです。

関数の引数で渡す

Enumの定数(caseオブジェクト)は変数代入ができるので、関数の引数で渡すこともできます。

function test(Color $color) {
    var_dump($color);
}

test(Color::Red);
実行結果
enum(Color::Red)

instanceofの結果でも分かるように、caseクラスはデータ型には使えないので、関数のパラメータの型にはenumクラスじゃないと使えません。

function test(Color::Red $color) {
    var_dump($color);
}

test(Color::Red);
実行結果
PHP Parse error:  syntax error, unexpected token "::", expecting variable in /home/vagrant/enum.php on line 13

また、enumクラスのオブジェクトは変数に代入できないので、関数のパラメータに渡すこともできません。

function test(Color $color) {
    var_dump($color);
}

test(Color);
実行結果
PHP Fatal error:  Uncaught Error: Undefined constant "Color" in /home/vagrant/enum.php:17
Stack trace:
#0 {main}
  thrown in /home/vagrant/enum.php on line 17

Enum のキャスト

Enumは特殊でもクラスには変わりはないので、object型にキャストすることができます。

データの破損もありません。

$val = (object)Color::Red;
var_dump($val);
var_dump($val->name);
enum(Color::Red)
string(3) "Red"

配列にキャストすることも可能。

$val = (array)Color::Red;
var_dump($val);
array(1) {
  ["name"]=>
  string(3) "Red"
}

上記以外の型にはキャストできません。

cases() で定数一覧を取得

enumクラスには唯一メソッドがあります。定数一覧を取得します。

var_dump(Color::cases());
実行結果
array(6) {
  [0]=>
  enum(Color::Red)
  [1]=>
  enum(Color::Green)
  [2]=>
  enum(Color::Blue)
  [3]=>
  enum(Color::Yellow)
  [4]=>
  enum(Color::White)
  [5]=>
  enum(Color::Black)
}

リストの中身は文字列ではなくcaseクラスのオブジェクト。定数そのもの。

enumクラスは内部で、cases() を定義したUnitEnum インターフェイスをimplementsしているので、すべての列挙型にはcases()が実装されてます。

cases()はオーバーライドできません。

PHP公式ドキュメント

Interface - UnitEnum

Enumも一種のクラスなので、自作のメソッド、インターフェイスの実装から、定数の定義までできます。traitの実装もできる。

PHP8.1以降しか動かない

Enum(列挙型)はPHP8.1に導入された機能なので、当然ですがPHP8.0以前は使えません。エラーになります。

PHP8.0でのエラー
PHP Parse error:  syntax error, unexpected identifier "Color" in /home/vagrant/enum.php on line 3
PHP7.4でのエラー
PHP Parse error:  syntax error, unexpected 'Color' (T_STRING) in /home/vagrant/enum.php on line 3

下位互換はまったくないので、PHP8.1以上で運用するというかなり限定的なものじゃないかぎり使えないな。

下位互換用に自作のクラスで似たようなものを作れなくもないけど、その作業がめんどくさい。

Enum を使うのは、PHP8.1以上が主流になるまで待ったほうがいいかもしれない。

Enumには2種類がある

今回は定数値のない定数を定義しましたが、定数値を定義するEnumもあります。Backed Enum と言います。

それに対して、定数値のない Enum のことを Pure Enum と言います。

また、定数値があるcaseを Backed Case、定数値がないものを Pure Case と言います。

前の投稿
PHP8.1, ついに追加されたEnum(列挙型)。...で、それは何? 何のためのもの?
PHP8.1, 定数値を入れる列挙型(Enum)。Backed Enum と言うらしい。
次の投稿

コメントを残す