16. final class GameDifficulty {
const HARD = 'hard';
const NORMAL = 'normal';
const EASY = 'easy';
use EnumTrait {
constant as public HARD;
constant as public NORMAL;
constant as public EASY;
}
}
// ↓ DocComment なしに補完できる!
$difficulty = GameDifficulty::NORMAL();
var_dump($difficulty->is(GameDifficulty::NORMAL())); // bool(true)
var_dump($difficulty->is(CheeseType::HARD())); // Type Error
// ↑ PhpStorm ならば警告表示される!
17. Point
• trait を利用することで、`self` タイ
プヒンティング(型宣言)が、use され
たクラスを表すことになる (is)
• use … as でメソッドを複数指定するこ
とで、メソッドが複製され、 static 変
数がメソッド分用意される (constant)
• Singleton にすることで、オブジェクト
自身の比較が定数値の比較と同じことに
なる
18. private static $instance; // use したクラスごとに個別に存在
/**
* @return self
*/
private static function constant()
{
static $name = null; // use … as したメソッドごとに個別に存在
if ($name === null) {
$name = debug_backtrace(
DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0][‘function’];
}
if (!isset(self::$instance[$name])) {
$cls = __CLASS__; // これは use した クラス名に置き換わる
self::$instance[$name] = new $cls(constant("{$cls}::{$name}"));
}
return self::$instance[$name];
}
}
19. trait EnumTrait
{
private $value;
public function __construct($value)
{
$ref = new ReflectionObject($this);
$cons = $ref->getConstants();
if (!in_array($value, $cons, true)) {
throw new InvalidArgumentException(“invalid constant value”);
}
$this->value = $value;
}
final public function value()
{
return $this->value;
}
final public function is(self $lhs) // この self は use したクラスを表す
{
return $this === $lhs;
}