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得了。