PHP枚举

378 阅读1分钟

PHP8.1新增

基础

Enum类似class

枚举的case可以定义0个或多个

枚举间对比没有意义,总是返回false。case是可以对比的

 <?php
 ​
 enum Colors
 {
      case Red;
      case Blue;
      case Green;
 ​
      public function getColor(): string
      {
          return $this->name;
      }
  }
 ​
 function paintColor(Colors $colors): void
 {
      echo "Paint : " . $colors->getColor() . PHP_EOL;
  }
 ​
 paintColor(Colors::Red);
 paintColor(Colors::Green);
 paintColor(Colors::Blue);
 ​
 /*
      output :
      ------------------------
      Paint : Red
      Paint : Green
      Paint : Blue
   */

回退枚举

case默认是类实现的,case可以赋值标量,这时case的类型会由复杂类型转为简单类型,这种称为回退

回退枚举只有一个value属性

回退枚举实现了BackedEnuminterface,额外暴露了from()tryFrom()方法

枚举值必须是确定的,不能是可变的

 <?php
 enum Suit: string
 {
     case Hearts = 'H';
     case Diamonds = 'D';
     case Clubs = 'C';
     case Spades = 'S';
 }
 ​
 print Suit::Clubs->value;
 print Suit::from('H');
 print Suit::tryFrom('XX') ?? Suit::Hearts;

枚举方法

枚举能定义自己的方法、静态方法,也能实现interface,但是不支持继承

因为不支持继承所以访问修饰符没什么用,都有public即可

 <?php
 interface Colorful
 {
     public function color(): string;
 }
 ​
 enum Suit implements Colorful
 {
     case Hearts;
     case Diamonds;
     case Clubs;
     case Spades;
 ​
     // 满足 interface 契约。
     public function color(): string
     {
         return match($this) {
             Suit::Hearts, Suit::Diamonds => 'Red',
             Suit::Clubs, Suit::Spades => 'Black',
         };
     }
 ​
     // 不是 interface 的一部分;也没问题
     public function shape(): string
     {
         return "Rectangle";
     }
     
     // 静态方法
     public static function fromLength(int $cm): static
     {
         return match(true) {
             $cm < 50 => static::Hearts,
             $cm < 100 => static::Diamonds,
             default => static::Clubs,
         };
     }
     
 }
 ​
 function paint(Colorful $c) { ... }
 ​
 paint(Suit::Clubs);  // 正常
 ​
 print Suit::Diamonds->shape(); // 输出 "Rectangle"

枚举常量

 <?php
 enum Size
 {
     case Small;
     case Medium;
     case Large;
 ​
     public const Huge = self::Large;
 }

使用Trait

在enum中使用trait时,不允许trait中包含属性,只能存在方法、静态方法