列挙型(Enum)にはメソッドやインターフェイスが追加できるように、トレイト(trait)も追加できます。
トレイトはメソッドをまとめたもので、インターフェイスやクラスの継承とは別のメソッド共通使用の方法です。
Enumだからといって特別なことはありません。使い方は通常のクラスと同じ。
インターフェイスとメソッドをトレイトに移動してみよう!
トレイト(trait)は、インターフェイスやクラスの継承を使わずに、メソッドを共通化するためのものです。
サンプルコードのインファーフェイス・メソッドをトレイトに変えてみましょう。
元のコード
interface Colorful
{
public function color(): string;
public static function names(): array;
}
enum Car implements Colorful
{
case MATUDA;
case HONDA;
case TOYOTA;
case SUZUKI;
public function color(): string
{
return match($this) {
Car::MATUDA => 'Black',
Car::HONDA => 'Red',
Car::TOYOTA => 'White',
Car::SUZUKI => 'Green',
};
}
public static function names(): array
{
return array_column(self::cases(), 'name');
}
}
traitのコード
trait Ext {
public function color(): string
{
return match($this) {
Car::MATUDA => 'Black',
Car::HONDA => 'Red',
Car::TOYOTA => 'White',
Car::SUZUKI => 'Green',
};
}
public static function names(): array
{
return array_column(self::cases(), 'name');
}
}
enum Car
{
use Ext;
case MATUDA;
case HONDA;
case TOYOTA;
case SUZUKI;
}
実行
var_dump(Car::HONDA->color());
var_dump(Car::MATUDA->names());
var_dump(Car::names());
実行結果
string(3) "Red"
array(4) {
[0]=>
string(6) "MATUDA"
[1]=>
string(5) "HONDA"
[2]=>
string(6) "TOYOTA"
[3]=>
string(6) "SUZUKI"
}
array(4) {
[0]=>
string(6) "MATUDA"
[1]=>
string(5) "HONDA"
[2]=>
string(6) "TOYOTA"
[3]=>
string(6) "SUZUKI"
}
Car と self のちがいについて
上記のサンプルコードでは、メソッド内の Car と self は同じです。self はトレイトを使うクラス自身のことを指すので、ここでは Car になる。
しかし、もし use Ext を入れるクラスが Car とはまったくちがう場合は、selfの意味が変わってくるので注意が必要。
またトレイトは、メソッドだけ記述するものなので、caseキーワードやconstは定義できません。
このへんのルールは通常のクラスで使うときと同じなので、困ることはないでしょう。列挙型(Enum)だからといって特別なことはありません。
PHP公式ドキュメント