php-tool-box:enum
PHPでEnumを使う
VBではおなじみのEnumをPHPで使えるように、クラスを作ってみる。
まずは定数としてEnumを定義できるクラス。
定数としてEnumを定義できるクラス
やはりEnumは定数っぽく使いたい。
<?php class Enum { const IS_NOT_MEMBER = -1; private static $_values = array(null); // 0番目は間違いの元になるので使わない public static function define($group, array $members) { // グループ名をstatic変数に追加&定数として定義 $num = array_push(self::$_values, self::IS_NOT_MEMBER) - 1; define($group, $num); // グループ内の要素をstatic変数に追加&定数として定義 foreach ($members as $member) { define($group . '_' . $member, array_push(self::$_values, $num) - 1); } } public static function typeof($memberNum) { return self::$_values[$memberNum]; } }
動作確認
// Enumを定義 Enum::define('ANIMAL', array('DOG', 'CAT')); Enum::define('FOOD', array('BANANA')); // 引数の種類を判定する function test($var) { if (Enum::typeof($var) === ANIMAL) { // このグループに含まれるか? if ($var === ANIMAL_DOG) { echo 'dog.'; } else { echo 'not dog.'; } } else { echo 'not animal.'; } } // 実行結果 test(ANIMAL_DOG); // => 'dog.' test(ANIMAL_CAT); // => 'not dog.' test(FOOD_BANANA); // => 'not animal.' test(ANIMAL_DAG); // 未定義の場合 => 'not animal.'
Type Safeでないのが残念。
Enumなら引数で型チェックしたい。
Type SafeなEnumを定義するクラス
<?php class Enum { public static function define($group, array $members) { // グループ名をinterfaceとして宣言 if (!interface_exists($group, false)) { eval("interface $group {}"); } // グループ内の要素をclassとして宣言 foreach ($members as $member) { if (!class_exists($member, false)) { eval("class $member extends Enum implements $group {}"); } } } public function is($type) { if (!class_exists($type, false) && !interface_exists($type, false)) { throw new Exception("$type is not defined"); } return $this instanceof $type; } }
動作確認
// Enumを定義 Enum::define('Animal', array('Dog', 'Cat')); Enum::define('Food', array('Banana')); // 引数がDogか判定する function test(ANIMAL $var) { if ($var->is('Dog')) { // switchの場合はis()は使えないので get_class($var) で echo 'dog.'; } else { echo 'not dog.'; } } // 実行結果 test(new Dog()); // => 'dog.' test(new Cat()); // => 'not dog.' //test(new Banana()); // ANIMALでない(引数の型不一致エラー) => Catchable fatal error //test(new Dag()); // 未定義の場合(class不明エラー) => Fatal error // グループに属するか判定する $banana = new Banana(); if ($banana->is('Food')) { // グループに属していればtrueになる echo 'food.'; } else { echo 'not food.'; }
引数の型チェックができる。
でもEnumを定数として使えないのが残念。
php-tool-box/enum.txt · 最終更新: 2011/07/01 23:06 by dgbadmin