對於PHP中enum的好奇


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM