PHP 8.4.1 Released!

枚举方法

枚举(包括纯粹枚举、回退枚举)还能包含方法, 也能实现 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"
?>

在这例子中,Suit 所有的四个实例具有两个方法: color()shape()。 目前的调用代码和类型检查,和其他对象实例的行为完全一致。

在回退枚举中,interface 的声明紧跟回退类型的声明之后。

<?php

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

enum
Suit: string implements Colorful
{
case
Hearts = 'H';
case
Diamonds = 'D';
case
Clubs = 'C';
case
Spades = 'S';

// 满足 interface 的契约。
public function color(): string
{
return match(
$this) {
Suit::Hearts, Suit::Diamonds => 'Red',
Suit::Clubs, Suit::Spades => 'Black',
};
}
}
?>

在方法中,定义了 $this 变量,它引用到了条目实例。

方法中可以任意复杂,但一般的实践中,往往会返回静态的值, 或者为 $this match 各种情况并返回不同的值。

注意,在本示例中,更好的数据模型实践是再定一个包含 Red 和 Black 枚举值的 SuitColor 枚举,并且返回它作为代替。 然而这会让本示例复杂化。

以上的层次在逻辑中类似于下面的 class 结构(虽然这不是它实际运行的代码):

<?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() 方法
// 参考 “枚举值清单” 章节
}
}
?>

尽管 enum 可以包括 public、private、protected 的方法, 但由于它不支持继承,因此在实践中 private 和 protected 效果是相同的。

添加备注

用户贡献的备注 1 note

up
7
iloveyii at yahoo dot com
1 year ago
Just to complete the function shape in the above neat example:

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

enum
Suit implements Colorful
{
case
Hearts;
case
Diamonds;
case
Clubs;
case
Spades;

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

// Not part of an interface; that's fine.
public function shape(): string
{
return match(
$this) {
Suit::Hearts => '❤️',
Suit::Diamonds => '💎',
Suit::Clubs => '♣️',
Suit::Spades => ' ♠️'
};

}
}

echo
Suit::Diamonds->shape();
echo
PHP_EOL;
echo
Suit::Clubs->shape();
To Top