こんにちは。よっしーです(^^)
今日は、PHPの列挙型(Enum)についてご紹介します。
背景
PHP8.2を利用したAPIを開発しているときに列挙型(Enum)を利用したので、そのときの調査内容を備忘としてのこしました。
こちらのサイトを参考にしています。
列挙型(Enum)メソッド
列挙型(”Pure Enum”と”Backed Enum”の両方)はメソッドを含むことができ、インターフェースを実装することもできます。列挙型がインターフェースを実装する場合、そのインターフェースの型チェックはその列挙型のすべてのケースを受け入れます。
interface Colorful
{
public function color(): string;
}
enum Suit implements Colorful
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
// インターフェースの実装
public function color(): string
{
return match($this) {
Suit::Hearts, Suit::Diamonds => 'Red',
Suit::Clubs, Suit::Spades => 'Black',
};
}
// インターフェースの一部ではないが、問題ありません。
public function shape(): string
{
return "Rectangle";
}
}
function paint(Colorful $c) { ... }
paint(Suit::Clubs); // 動作します
print Suit::Diamonds->shape(); // "Rectangle" を表示
この例では、Suitの4つのインスタンスは2つのメソッド、color() および shape() を持っています。呼び出しコードと型チェックに関しては、他のオブジェクトインスタンスとまったく同じように動作します。
バックアッド列挙型では、インターフェース宣言はバックアッドタイプ宣言の後に続きます。
interface Colorful
{
public function color(): string;
}
enum Suit: string implements Colorful
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
// インターフェースの実装
public function color(): string
{
return match($this) {
Suit::Hearts, Suit::Diamonds => 'Red',
Suit::Clubs, Suit::Spades => 'Black',
};
}
}
メソッド内では、$this
変数が定義され、ケースインスタンスを参照します。メソッドは任意の複雑さを持つことができますが、実際には通常、静的な値を返したり、 $this
に対してマッチングして異なるケースに異なる結果を提供します。
ただし、この場合、より良いデータモデリングの実践として、SuitColor Enum型を定義し、その値を返す方が良いです。ただし、この例を複雑にすることになります。
上記の階層は、論理的には次のクラス構造に似ています(これは実際の実行コードではありません):
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
{
// 手動で列挙型の cases() メソッドを定義することは許可されていません。
// "値一覧" セクションも参照してください。
}
}
メソッドは public、private、または protected にすることができますが、実際のところ private と protected は継承が許可されていないため、同等です。
列挙型(Enum)静的メソッド
列挙型(Enum)は静的メソッドも持つことができます。列挙型自体の静的メソッドの主な用途は、代替コンストラクタです。たとえば:
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,
};
}
}
静的メソッドは public、private、または protected にすることができますが、実際のところ private と protected は継承が許可されていないため、同等です。このような静的メソッドは、列挙型内で新しいインスタンスを作成したり、特定の条件に基づいて既存の列挙型のケースを返したりする際に便利です。
おわりに
今日は、PHPの列挙型(Enum)についてご紹介しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント