最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • PHP中实现JAVA枚举功能

    正文概述 转载于:掘金(yinfuyuan)   2021-01-06   325

    概述

    在迭代了N个版本后,终于在目前最新的版本中实现了和Java枚举定义使用都非常相似的php枚举库php-enum

    这里有必要提一下为什么非要实现Java枚举功能。我是在Java中认识枚举的,在此之前,我使用PHP很长时间也没有听说的过枚举,但在Java的项目中,枚举随处可见,尤其是在API返回统一状态码的场景中,它已经快成为了规范,所以我并没有办法忽略它,于是也学着使用它,等我再使用PHP的时候发现已经不太习惯没有枚举,于是感觉去搜索PHP的枚举

    众所周知,在PHP中要使用枚举有两个选择,一个是官方在SPL中提供的枚举库,看到这里,是不是特别开心。别急,阅读文档后你会发现,你不仅要以拓展的方式安装它,它提供的方法也非常有限。所以通常我们会选择第二种方式,也就是使用第三方的枚举库。而通过阅读第三方的枚举的源码你也会发现,它们或多或少都有Java枚举的影子。但如果它们实现了Java枚举的功能也就不会有今天的库和文章了。

    我查了很多枚举,发现它们都缺少Java枚举中的核心功能,也就是自定义属性值(在Java枚举中,枚举并不是简单的定义常量名称和常量值,你可以定义属性来承载枚举中的元素)同时也发现在php中实现这个功能并不容易,于是我在项目中写了个抽象类来实现固定两个属性的功能,因为要在多个项目中使用,就将它放到了github上,之后经过多次重构,一次次推翻自己的想法,最终终于接近了Java枚举的实现

    安装

    composer require phpenum/phpenum
    

    快速开始

    PHPEnum用起来和Java枚举很像,比如定义一个表示性别的枚举

    在Java中:

    public enum GenderEnum {
        MALE(1, "male"),
        FEMALE(2, "female");
    
        private Integer id;
        private String name;
    
        GenderEnum(Integer id, String name) {
            this.id = id;
            this.name = name;
        }
    
        public Integer getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    }
    

    使用PhpEnum:

    class GenderEnum extends \PhpEnum\Enum
    {
        const MALE = [1, 'male'];
        const FEMALE = [2, 'female'];
    
        private $id;
        private $name;
    
        protected function construct($id, $name)
        {
            $this->id = $id;
            $this->name->$name;
        }
    
        public function getId()
        {
            return $this->id;
        }
        
        public function getName()
        {
            return $this->name;
        }
    }
    

    你会发现它们的用法也非常相似

    在Java中:

    GenderEnum.values(); // enum instance array
    GenderEnum.valueOf("FEMALE"); // enum instance
    GenderEnum.MALE.equals(GenderEnum.valueOf("MALE")); // true
    GenderEnum.MALE.name(); // MALE
    GenderEnum.MALE.ordinal(); // 0
    GenderEnum.MALE.toString(); // MALE
    GenderEnum.MALE.getId(); // 1
    GenderEnum.MALE.getName(); // male
    

    使用PhpEnum:

    GenderEnum::values(); // enum instance array
    GenderEnum::valueOf('FEMALE'); // enum instance
    GenderEnum::MALE()->equals(GenderEnum::valueOf('MALE')); // true
    GenderEnum::MALE()->name(); // MALE
    GenderEnum::MALE()->ordinal(); // 0
    (string)GenderEnum::MALE(); // MALE
    GenderEnum::MALE()->getId(); // 1
    GenderEnum::MALE()->getName(); // male
    

    不仅如此,PhpEnum还在子类中提供了高级功能

    GenderEnum::MALE()->idEquals(1); // true
    GenderEnum::MALE()->NameEquals('male'); // true
    GenderEnum::containsId(1); // 1
    GenderEnum::containsName('male'); // 1
    GenderEnum::ofId(1); // enum instance
    GenderEnum::ofName('male'); // enum instance
    

    PHPEnum是为PHP开发人员准备的枚举类库,它由基础类 Enum 和拓展类 PhpEnum 构成。 其中基础类完全参考了 Java枚举 并实现和其相似的功能。 而拓展类是通过结合PHP的语言特性实现了一些快速访问的方法。

    基础类Enum

    基础类完全参考了Java枚举,如果你之前了解Java枚举,那么在这里你可以以相同的方式使用它。

    在Java中定义的枚举常量格式为构造参数的调用,在无参数时括号和构造方法可以省略,在有参数时,必须提供和参数格式相对应的构造方法。

    例:

    // 无参数时括号和构造方法可以省略
    public enum Color {
        RED, GREEN, BLUE;
    }
    
    // 有参数时必须要提供正确的构造方法
    public enum Color {
        RED("FF0000"), GREEN("00FF00"), BLUE("0000FF");
    
        Color(String hexadecimal) {
        }
    }
    

    但在PHP中,PHP的语法并不允许我们这样做,所以PhpEnum使用常量数组来表示构造方法中的参数,在无参时构造方法可以省略但参数数组不可省略,在有参数时,必须提供和参数格式相对应的构造方法。

    PhpEnum中的构造方法名称为construct且必须使用protected来修饰

    例:

    // 无参数时构造方法可以省略,但参数数组必须为空数组
    class Color extends \PhpEnum\Enum
    {
        const RED = [];
        const GREEN = [];
        const BLUE = [];
    }
    
    // 有参数时必须要提供正确的构造方法
    class Color extends \PhpEnum\Enum
    {
        const RED = ["FF0000"];
        const GREEN = ["00FF00"];
        const BLUE = ["0000FF"];
    
        protected function construct(string $hexadecimal)
        {
        }
    }
    

    在实际使用中,我们通常需要对参数定义与其对应的属性和属性的getter使其可以对外访问

    例:

    class Color extends \PhpEnum\Enum
    {
        const RED = ["FF0000"];
        const GREEN = ["00FF00"];
        const BLUE = ["0000FF"];
    
        private string $hexadecimal;
    
        protected function construct(string $hexadecimal)
        {
            $this->hexadecimal = $hexadecimal;
        }
    
        public function getHexadecimal(): string
        {
            return $this->hexadecimal;
        }
    }
    

    基础类为我们提供了如下方法

    • name:string 返回枚举的名称
    • ordinal:int 返回枚举定义的序,从0开始
    • equals:bool 与另一枚举对比是否相等
    • static values:static[] 返回所有枚举实例,正确的使用参数prefix可以减少内存开销,也可以在存在相同枚举值时返回正确的结果,虽然不建议在同一个枚举中定义相同值
    • static valueOf:static 根据枚举名称返回枚举实例

    拓展类PhpEnum

    拓展类是基础类的子类,所以它与基础类的定义和使用方式完全相同,拓展类提供了更多方法来使用枚举。 拓展类提供的方法大多数与枚举属性相关,所以在使用拓展类时应正确定义属性以及属性的getter。

    例:

    class Color extends \PhpEnum\PhpEnum
    {
        const RED = ["FF0000"];
        const GREEN = ["00FF00"];
        const BLUE = ["0000FF"];
    
        private string $hexadecimal;
    
        protected function construct(string $hexadecimal)
        {
            $this->hexadecimal = $hexadecimal;
        }
    
        public function getHexadecimal(): string
        {
            return $this->hexadecimal;
        }
    }
    

    拓展类为我们提供了如下方法

    • get:mixed 获取一个属性值。注意这个方法并不能代替属性的getter,相反当你的属性使用private修饰时,你应该提供属性的getter以保证此方法的正确性,这是其他方法的基础(虽然通过反射也可以获取属性的值,但那样会带来很大的内存开销)
    • enumNameEquals:bool 判断枚举的名称和指定的名称是否相等
    • propertyEquals:bool 判断枚举的属性值和指定的属性值是否相等,注意当属性的类型是浮点类型时,会优先使用bccomp函数进行对比,你需要通过重写scale方法来设置正确的小数位数,设置全局生效
    • static containsEnumName:bool 判断枚举名称中是否包含指定的枚举名称
    • static containsProperty:int 返回枚举属性值等于指定值的枚举数量
    • static ofProperty:static 返回枚举属性值等于指定值的枚举实例,当找到的枚举数量大于1时,会抛出一个异常
    • static properties:array 返回所有枚举的某个属性值的数组
    • static names:string[] 返回所有的枚举名称
    • static count:int 返回所有枚举的数量

    拓展类对equalscontainsof提供了魔术方法触发的方式,也就是在方法中包含关键字和属性名称时,会自动找到正确的方法调用。

    例:

    var_dump(Color::RED()->hexadecimalEquals('FF0000')); // bool(true)
    var_dump(Color::containsHexadecimal('FF0000')); // int(1)
    var_dump(Color::ofHexadecimal('FF0000')); // object(Color)
    

    起源地下载网 » PHP中实现JAVA枚举功能

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元