※この記事はPocketMine-API 4.0.0が対象です
PMMPではEnumがPHP8.1じゃなくても使える!
PMMPには、EnumTraitというTrait(機能)が実装されているので、これを使うことで実装することができます。
Enumを使う理由
Enumを使用しない場合、例えば以下のようなコードになると思います。
class Trump
{
public const SUIT_CLUB = 0;
public const SUIT_DIAMOND = 1;
public const SUIT_HEART = 2;
public const SUIT_SPADE = 3;
private int $suit;
public function __construct(int $suit)
{
switch ($suit) {
case self::SUIT_CLUB:
case self::SUIT_DIAMOND:
case self::SUIT_HEART:
case self::SUIT_SPADE:
break;
default:
throw new InvalidArgumentException("Invalid suit");
}
$this->suit = $suit;
}
}
$trump = new Trump(Trump::SUIT_CLUB);
しかし、この方法には
- 型がintのため任意の値を渡すことができ、渡された値が不正でないか検証する必要がある
- 使う側が、何の値を入れれば良いのか直感的にわかりづらい
といった問題があります。
そこで列挙型を使うと次のようになり、問題を解決することができます。
class Trump
{
private Suit $suit;
public function __construct(Suit $suit)
{
$this->suit = $suit;
}
}
$trump = new Trump(Suit::CLUB());
※Suitクラスはこれから説明するため省略
引数が整数ではなくクラスであるため値の検証がいらず、渡す側もタイプヒンティングによって分かりやすくなります。
Enumクラスの作り方
Enumを使用するためには、pocketmine\utils\EnumTrait
をuseしたクラスを定義する必要があります。
※クラス外に置いているよく使うuseとは意味が違うので注意!
(この記事で作成する)Enumクラスは継承されることを想定していないので、クラスにfinalと指定しておきましょう。
setup()
メソッドの中で、Enumの要素を全て登録します。
ここではregisterAll()
メソッドを使用していますが、register()
メソッドを使用することもできます。コード
クラス定義の上に/** ~ */
で囲まれたDocブロックがありますが、これは主に静的解析ツールによる解析を補助するため(それによって生成されるドキュメント含む)であり、動作には影響ありませんが可読性のためにも書いておくことを推奨します。
この例では、トランプのマーク(Suit)のEnumを実装しています。
use pocketmine\utils\EnumTrait;
/**
* @method static Suit CLUB()
* @method static Suit DIAMOND()
* @method static Suit HEART()
* @method static Suit SPADE()
*/
final class Suit
{
use EnumTrait;
protected static function setup(): void
{
self::registerAll(
new self("club"),
new self("diamond"),
new self("heart"),
new self("spade"),
);
}
}
使い方
Enumを生成する
$suit = Suit::DIAMOND();//これはSuitクラスのインスタンス
Enumの名前を取得する
$suit = Suit::DIAMOND();
$suit->name();//string "diamond"
Enumの数値IDを取得する
これは配列のインデックスなどに使用します。この値はサーバーを起動するたびに変わるので、Configに保存するなどの用途には使用できません。
$suit = Suit::DIAMOND();
$suit->id();//int 0
EnumがBであるか
$suit = Suit::DIAMOND();
$suitB = Suit::HEART();
$suit->equals($suitB);//bool false