PHPでJava風のEnum

PHPでJava風のEnumを使いたい。
valuesとかvalueOfとか複数の値を持たせたい。
そんな人向けなEnumを強引に作ってみました。

下記Enumクラスを継承して作ります。
■Enum.php

class Enum{
	public static $enumArray = array();
	public static $ordinalCntArray = array();
 
	private $ordinalCnt;
	protected function __construct($inEnum){
		$tmpArray = &self::$enumArray[get_class($inEnum)];
		if($tmpArray == ""){
			$tmpArray = array();
			array_push($tmpArray, $inEnum);
			self::$enumArray[get_class($inEnum)] = $tmpArray;
		}else{
			array_push($tmpArray, $inEnum);
		}
 
		$this->ordinalCnt = self::$ordinalCntArray[get_class($inEnum)];
 
		if(is_null($this->ordinalCnt) || $this->ordinalCnt === ""){
			$this->ordinalCnt = 0;
			self::$ordinalCntArray[get_class($inEnum)] = $this->ordinalCnt;
		}else{
			$this->ordinalCnt++;
			self::$ordinalCntArray[get_class($inEnum)] = $this->ordinalCnt;
		}
	}
	function ordinal(){
		return $this->ordinalCnt;
	}
	public static function values($inEnum){
		return self::$enumArray[get_class($inEnum)];
	}
}

継承の仕方は次のようにします

■EPerson.php

<?php
class EPerson extends Enum{
	private $name;
	private $jaName;
	private $tel;
	/**
	 * @var EPerson
	 */
	public static $taro;
	/**
	 * @var EPerson
	 */
	public static $takashi;
	/**
	 * @var EPerson
	 */
	public static $hanako;
	function __construct($inName, $inJaName, $inTel){
		$this->name = $inName;
		$this->jaName = $inJaName;
		$this->tel = $inTel;
		parent::__construct($this);
	}
	public static function init(){
		self::$taro = new EPerson("taro", "山田太郎", "000-1111-2222");
		self::$takashi = new EPerson("takashi", "佐藤隆", "000-333-4444");
		self::$hanako = new EPerson("hanako", "鈴木花子", "000-5555-6666");
	}
	public function getName(){
		return $this->name;
	}
	public function getJaName(){
		return $this->jaName;
	}
	public function getTel(){
		return $this->tel;
	}
	public static function values(){
		return parent::values(EPerson::$taro);
	}
}
EPerson::init();

上から順に説明していきます。
まず、Enumの継承。EPersonクラスにEnumを継承させています。
次に内部用の変数。

private $name;
private $jaName;
private $tel;

これが一つのEnumに対しての取得できる値になります。
ここではname, jaName, telの三つです。

次に外部用の変数。

/**
 * @var EPerson
 */
public static $taro;
/**
 * @var EPerson
 */
public static $takashi;
/**
 * @var EPerson
 */
public static $hanako;

これらはEnumとして使用する変数になります。
各変数は内部用の変数 name, jaName, tel を持っています。

@var EPerson 等のコメントはeclipse上でコード補完をするために行っています。
EPerson::$hanako->」のときにCTRL+SPACEでメソッド一覧が出てくるので便利です。

次にコンストラクタ

function __construct($inName, $inJaName, $inTel){
	$this->name = $inName;
	$this->jaName = $inJaName;
	$this->tel = $inTel;
	parent::__construct($this);
}

これはそのまま貰った引数を各内部用の変数に入れて最後に親コンストラクタを読んで終わりです。

・初期化init()で外部用の変数 $taro, $takashi, $hanakoEPersonオブジェクトを生成してあげます。
この
init()メソッドはこのプログラムの最後で必ず呼び出してあげます。

次にgetterメソッド getName()getJaName(), getTel() は各内部変数を取得するために使います。
echo EPerson::$hanako->getName(); 」 のように使います。

valuesはオーバーライドする必要があります。
親メソッドにクラス名を教えてあげないといけないため適当なEPersonオブジェクトを入れています。
ここではEPerson::$taro。これでEPerson::values()を呼び出すとEPersonの値がtaro,takashi,hanako全てが配列で返ってきます。

最後にクラスの外でinit()メソッドを呼び出して完了です。

Enumの変数が一つ増えるたびにオブジェクトが増えていくので高コストな気がしますがJava風でやるならこれしか方法が思いつきませんでした。まぁJavaのほうも一つのEnumの変数に対してオブジェクト一つ生成されるから同じかな。

EPerson::$hanako->ordinal() とやるとinit()内での生成順のindexが取得できます。開始位置は0です。

プログラムを置いておきますのでJava風Enumを使いたいという方は参考にどうぞお使いください。
動作の確認はしてないのですがたぶん動くでしょう。
ファイル名が大文字なのはJava風のためです。
ちなみにvalueOfは良い実装方法が思いつかなかったのでありません。

download
: Enum.php
: EPerson.php

Follow me!

PHPでJava風のEnum” に対して1件のコメントがあります。

  1. Bert より:

    A piece of erotidiun unlike any other!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です