PHP中沒有struct、enum這些東西,雖然萬能的array用起來很爽,但寫出來的代碼typo問題很多、可維護性也差,需要更多的測試來輔助,而一旦加上測試的工作量是否還談得上『爽』就是個問號了。
看了一篇研究Java enum機制的文章,文章里提到java的具體的enum其實就是一個類,重點是它的每一個枚舉值也是一個enum對象。
對照着用PHP初步實現了一下。PHP的__callStatic 不支持靜態屬性訪問,所以暫時用靜態方法的形式訪問枚舉值 (string) Color::RED()。
<?php
interface enum
{
}
/**
* @method enum RED() Description
*/
final class Color implements enum
{
private static $enums =
[
'RED' => [255, 0, 0],
'BLUE' => [0, 0, 255],
'BLACK' => [0, 0, 0],
'YELLOW' => [255, 255, 0],
'GREEN' => [0, 255, 0]
];
private static $objs = [];
private $name;
public static function __callStatic($name, $arguments)
{
if (!array_key_exists($name, static::$enums)) {
throw new Exception('enum not existed', -1);
}
return static::valueOf($name);
}
private function setName($val): void
{
$this->name = $val;
}
private static function initEnum(string $name): bool
{
if (isset(static::$objs[$name])) {
return true;
}
if (!array_key_exists($name, static::$enums)) {
throw new Exception('enum not existed', -1);
}
$obj = new Color();
$obj->setName($name);
static::$objs[$name] = $obj;
return true;
}
public static function values(): array
{
if (empty(static::$objs)) {
foreach (array_keys(static::$enums) as $name) {
static::initEnum($name);
}
}
return static::$objs;
}
public static function valueOf(string $name): enum
{
if (!array_key_exists($name, static::$enums)) {
throw new Exception('enum not existed', -1);
}
static::initEnum($name);
return static::$objs[$name];
}
public function ordinal(): int
{
//TODO
return 0;
}
/**
* @throws ClassCastException
*/
public function compareTo(enum $other): int
{
//TODO
return -1;
}
public function equals(enum $other): bool
{
//TODO
return true;
}
public function __toString()
{
if (!$this->name) {
return '';
}
return '(' . implode(',', static::$enums[$this->name]) . ')';
}
}
echo (string) Color::RED();
echo (string) Color::valueOf('BLACK');
代碼並沒有做細致的抽象,如果要進一步抽象的話,可以試試定義一個EnumTraits來包含那些公共方法。
會不會有人問,既然你這么喜歡Java的enum,為什么不直接用Java得了。