概要
- PHPのEnumについてちゃんと理解してまとめる
Enumって?
- 取りうる値を限定した独自の型を定義できるクラスに似ているもの。
- 似ているだけでクラスではない。クラスやオブジェクトの上に構築されている。
Enumのルール
- コンストラクタ、デストラクタは書けない。
- 継承をすることも継承されることもできない。
- プロパティーは許可されていない。
- caseをcloneすることはサポートされていない。
- 使う前に宣言しないといけない。
- newを使って直接インスタンス化できない。
-
__call
と__callStatic
と__invoke
以外のマジックメソッドは許可されていない。 -
__CLASS__
と__FUNCTION__
以外のマジック定数は許可されていない。 - インターフェースの実装可能
- アトリビュートを深する事が可能
- 定義可能メソッド
- public
- private
- protected
- 定義可能staticメソッド
- public
- private
- protected
Enumの種類
PureEnum
-
PureCaseだけを含むEnumのこと。
-
PureCase
- 関連するデータが無い名前だけのCase
-
例
<?php enum Suit { case Hearts; case Diamonds; case Clubs; case Spades; }
-
読み取り専用プロパティーのnameがある。下記にようにEnumを呼び出すことでcaseで定義されているcaseそのものの名前を得ることができる。
<?php // Heartsが格納される $suit = Suit::Hearts->name;
BackedEnum
-
スカラー値を持つCaseが含まれるEnumのこと。
-
スカラー値
- スカラー型の値のこと
- PHPだと論理型(bool)、整数型(int)、浮動小数点型(float, double, real)、文字列型(string)がスカラー型
-
例
<?php enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; }
-
一つのEnumで持てるスカラー値の型は一つだけ。下記みたいな書き方はできない。(そもそも
enum Suit: string|int
という書き方ができない。仮にenum Suit: string
でスカラー値がstringとintが入り混じっていたら「Enum定義時のstring型とマッチしない物があるエラー」が出る。)<?php enum Suit: string|int { case Hearts = 'H'; case Diamonds = 1; case Clubs = 'C'; case Spades = 2; }
-
スカラー値はユニークである必要がある。下記みたいな書き方はできない。
<?php enum Suit: string { case Hearts = 'H'; case Diamonds = 'H'; case Clubs = 'H'; case Spades = 'H'; }
-
読み取り専用プロパティーのvalueがある。下記のように記載することでcaseの名前に紐づくスカラー値を取得する事ができる。
<?php // Hが格納される $suitValue = Suit::Hearts->value;
-
BackedEnumはBackedEnumインターフェースを実装しているらしい。そのためfromとtryFromという2個のstaticな関数を呼び出す事ができる。
-
from関数を使って値からEnumのインスタンスを取得する。
-
下記のようにfrom関数を用いることで引数の値とcaseに紐づくスカラー値を比較、一致するものがあれば当該caseのオブジェクトを返す。(引数とスカラー値の比較はPHP側の設定で「強い比較」「弱い比較」を選択できる。強い比較 → PHP declare(strict_types=1)ってなんだ!?)
<?php enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } $suit = Suit::from('H'); // enum(Suit::Hearts)と出力される var_dump($suit);
-
引数の値がcaseに紐づくスカラー値のいずれとも一致しなかった場合エラーを返す。
<?php enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } // エラー発生 「PHP Fatal error: Uncaught ValueError: "X" is not a valid backing value for enum "Suit"」 $suit = Suit::from('X');
-
-
tryFrom関数を用いて値からEnumのインスタンスを取得する。
-
下記のようにtryFrom関数を用いることでfrom関数の時と同様の振る舞いをする。
<?php enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } $suit = Suit::tryFrom('H'); // enum(Suit::Hearts)と出力される var_dump($suit);
-
引数の値がcaseに紐づくスカラー値のいずれとも一致しなかった場合nullを返す。
<?php enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } $suit = Suit::tryFrom('X'); // nullと出力される var_dump($suit);
-
関数の定義
-
PureEnum、BackedEnum共に関数を定義することは可能である。(public, private, protectedの関数が定義できるけど、結局Enumは継承できないから何を指定してもprotectedと実質は同じ)
-
例
<?php enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; public function foo(){ return 'トランプは楽しい'; } } $suit = Suit::Hearts->foo(); // 「トランプは楽しい」と出力される echo $suit;
-
トレイトをuseすることもできる。
<?php trait Values{ public function foo(){ return 'トランプは楽しい'; } } enum Suit: string { use Values; case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } $suit = Suit::Hearts->foo(); // 「トランプは楽しい」と出力される echo $suit;
-
下記のように記載すればPureEnumでも紐づく値を設定する事ができる。
<?php enum Suit { case Hearts; case Diamonds; case Clubs; case Spades; public function values(){ return match ($this) { Suit::Hearts => 'H', Suit::Diamonds => 'D', Suit::Clubs => 'C', Suit::Spades => 'S', }; } } // 「H」と出力される echo Suit::Hearts->values();
-
コンストラクタの代わりをさせたいならstatic関数を定義する。
<?php enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; public static function foo(int $int){ return match ($int) { 1 => Suit::Hearts, 2 => Suit::Diamonds, 3 => Suit::Clubs, 4 => Suit::Spades, }; } } $suit = Suit::foo(1); // 「enum(Suit::Hearts)」と出力される var_dump($suit);
Enumのcaseを配列で返す
-
下記のように記載することでEnumのcaseを宣言された順番で配列で取得する事ができる。
<?php enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } var_dump(Suit::cases());