📘
phpでファーストクラスコレクションを作る
概要
phpでファーストクラスコレクションを作ろうと思っても、配列の中身の型は言語仕様では縛れない。
可変長変数を使ったら配列の中身をforeach
でいちいち確認したりしなくてすむ。
以下、Account
クラスのファーストクラスコレクションであるAccounts
クラスについての実装を例とする。
パターン1: コンストラクタの引数を可変長変数にしてタイプヒントする
arrayから生成できても便利なのでfromArray
メソッドも作ってます
class Accounts
{
/** @var Account[] */
private array $accounts;
public function __construct(Account ...$accounts)
{
$this->accounts = $accounts;
}
static public function fromArray(array $accounts): self
{
return new self(...$accounts);
}
public function add(Account $account): self
{
return new self(...array_merge($this->accounts, [$account]));
}
}
$account1 = new Account('ichiro');
$account2 = new Account('jiro');
$account3 = new Account('saburo');
$accounts = new Accounts($account1, $account2, $account3);
// もしくは
$accounts = Accounts::fromArray([$account1, $account2, $account3]);
パターン2: 可変長変数を引数に取るprivateメソッドを定義して、そのメソッド経由で値をセットする
class Accounts
{
/** @var Account[] */
private array $accounts;
public function __construct(array $accounts)
{
$this->setValue(...$accounts);
}
private function setValue(Account ...$accounts): self
{
$this->accounts = $accounts;
}
public function add(Account $account): self
{
return new self(array_merge($this->accounts, [$account]));
}
}
$account1 = new Account('ichiro');
$account2 = new Account('jiro');
$account3 = new Account('saburo');
$accounts = new Accounts([$account1, $account2, $account3]);
パターン3: 可変長変数を引数に取る無名関数を定義して、その関数経由で値をセットする
パターン2とおなじやり方だが、コンストラクタ内で簡潔するのでこっちの方が個人的に好み
class Accounts
{
/** @var Account[] */
private array $accounts;
public function __construct(array $accounts)
{
$set_value = function (Account ...$accounts) {
$this->accounts = $accounts;
};
$set_value(...$accounts);
}
public function add(Account $account): self
{
return new self(array_merge($this->accounts, [$account]));
}
}
$account1 = new Account('ichiro');
$account2 = new Account('jiro');
$account3 = new Account('saburo');
$accounts = new Accounts([$account1, $account2, $account3]);
Discussion