2.7PHP类(Class)类型之枚举(Enumeration)

Enum 本质是一个类(Class),它的各种条目(case)是这个类的单例对象,又近似于可以理解为类常量。

<?php
interface Colorful
{
    public function color(): string;
}

final class Suit implements UnitEnum, Colorful
{
    public const Hearts = new self('Hearts');
    public const Diamonds = new self('Diamonds');
    public const Clubs = new self('Clubs');
    public const Spades = new self('Spades');

    private function __construct(public readonly string $name) {}

    public function color(): string
    {
        return match($this) {
            Suit::Hearts, Suit::Diamonds => 'Red',
            Suit::Clubs, Suit::Spades => 'Black',
        };
    }

    public function shape(): string
    {
        return "Rectangle";
    }

    public static function cases(): array
    {
        // 不合法的方法,Enum 中不允许手动定义 cases() 方法
        // 参考 “枚举值清单” 章节
    }
}
?>

1.纯粹(Pure)枚举

如果条目(case)没有关联数据,就称为“纯粹条目”(Pure Case)。

仅包含纯粹条目的枚举就称为“纯粹枚举“(Pure Enum)。

//PHP < 8.1
class Status
{
    const DRAFT = 'draft';
    const PUBLISHED = 'published';
    const ARCHIVED = 'archived';
}
function acceptStatus(string $status) {...}
//PHP 8.1
enum Status
{
    case Draft;
    case Published;
    case Archived;
}
function acceptStatus(Status $status) {...}

2.回退(Backed)枚举

由于有标量的条目回退(Backed)到一个更简单值,就称为“回退条目”(Backed Case)。

仅包含所有回退条目的枚举就称为“回退枚举”(Backed Enum)。

回退枚举仅能回退到 int 或 string 里的一种类型(不能联合 int|string)。

<?php
enum Suit: string
{
    case Hearts = 'H';
    case Diamonds = 'D';
    case Clubs = 'C';
    case Spades = 'S';
}
?>

3.访问case

<?php
enum Suit
{
    case Hearts;
    case Diamonds;
    case Clubs;
    case Spades;
}
?>

访问枚举的case类似于类访问类常量的方式。

Suit::Hearts、Suit::Diamonds、 Suit::Clubs、Suit::Spades

4.访问case的name和value

所有的 case 有个只读的属性 name。 它大小写敏感,是 case 自身的名称。 在调试场景中比较有用。

<?php
print Suit::Spades->name;
// 输出 "Spades"
?>

回退条目有个额外的只读属性 value, 它是定义时指定的值。

<?php
print Suit::Clubs->value;
// 输出 "C"
?>

5.枚举常量

枚举常量可以引用枚举条目:

<?php
enum Size
{
    case Small;
    case Medium;
    case Large;

    public const Huge = self::Large;
}
?>

6.枚举静态方法

枚举也能有静态方法。 在枚举中静态方法主要用于取代构造器,如:

<?php
enum Size
{
    case Small;
    case Medium;
    case Large;

    public static function fromLength(int $cm): static
    {
        return match(true) {
            $cm < 50 => static::Small,
            $cm < 100 => static::Medium,
            default => static::Large,
        };
    }
}
?>

7.枚举实例方法和实现接口

枚举(包括纯粹枚举、回退枚举)还能包含方法, 也能实现 interface。 如果 Enum 实现了 interface,则其中的条目也能接受 interface 的类型检测。

<?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";
    }
}

function paint(Colorful $c) { ... }

paint(Suit::Clubs);  // 正常

print Suit::Diamonds->shape(); // 输出 "Rectangle"
?>

8.继承

不支持继承。无法 extend 一个 enum。

9.构造函数和析构函数

禁止构造、析构函数。

10.静态变量和实例变量

不支持静态变量和实例变量。

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/php/phplang/10516.html

(0)
上一篇 2021年2月7日 03:40
下一篇 2021年2月8日 20:39

相关推荐

  • 2.5PHP复合(Compound)类型之可迭代(Iterable)

    可迭代(Iterable)类型的对象是任何 array 或 实现了 Traversable 接口的类的对象,否则会抛出一个 TypeError异常。 Traversable 接口是无法被单独实现的基本抽象接口,必须由 IteratorAggregate 或 Iterator 接口实现。 可迭代(Iterable)类型的…

    PHP语言教程 2021年2月5日
    02290
  • 1.8PHP语言的条件(Conditional)、循环(Loop)、跳转(Jump)语句

    1.if条件 2.if..else条件 3.if..elseif..else条件 4.switch..case条件 switch 语句类似于具有同一个表达式的一系列 if 语句。很多场合下需要把同一个变量(或表达式)与很多不同的值比较,并根据它等于哪个值来执行不同的代码,这正是 …

    PHP语言教程 2021年1月8日
    04040
  • 3.1PHP语言的命名空间(Namespace)

    什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。具体举个例子,文件 foo.txt 可以同时在目录 /home/greg 和 /hom…

    PHP语言教程 2021年3月1日
    04090

发表评论

登录后才能评论