blue32a
@blue32a (blue32a)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

イミュータブルなコレクションクラスでのshiftやpop

解決したいこと

イミュータブルなコレクションクラスにおいて、shiftpopなどの「コレクションを変更しつつ1要素を取得する処理」をどのように実装するか。

例)

言語はPHP。
トランプのデッキを示すDeckクラス。
デッキはカードのコレクション。
デッキの一番上からカードを一枚取得するshiftメソッドを実装する。取得したカードはデッキから無くなる。

Deck.php
class CardCollection
{
    /** @var Card[] */
    protected array $cards;
}

class Deck extends CardCollection
{
}

自分で試したこと

案1.デッキの一番上を示すindexを持たせる

Deck.php
class Deck extends CardCollection
{
    private int $topIndex;

    public function shift(): Card
    {
        $topCard = $this->cards[$this->topIndex];
        $this->topIndex++;
        return $topCard;
    }
}

問題点:countなどを実装する時にindexの考慮が必要になる。

案2.カードと新しいデッキを返す

Deck.php
class Deck extends CardCollection
{
    public function shift(): array
    {
        $cards = $this->cards;
        $topCard = array_shift($cards);
        $newDeck = new self($cards);
        return [$topCard, $newDeck];
    }
}

問題点:複数の値を返すことになる。(Resultクラスを作れば解決できそう)

質問

「案2.カードと新しいデッキを返す」が良いと考えているのですが、いかがでしょうか?
理由:デッキのカードが減っていくのを表現しやすいので

また、他の解決方法があればご教授いただきたいです。
PHP以外の言語でも歓迎します。

何卒よろしくお願いします。

0

1Answer

イミュータブルのコレクションは、shiftなどのインスタンスに変更を加える関数が呼ばれた場合に例外を投げるのが一般的だと思います。

案1はインデックスという状態を持った時点でイミュータブルでなくなります。
イミュータブルにこだわるなら案2です。
(そもそもデッキという概念はイミュータブルでないような気がしますが)

1Like

Comments

  1. @blue32a

    Questioner

    回答ありがとうございます。

    確かに、デッキの例ではカードを1枚ずつ減らしていくので、イミュータブルにする必要が無いのかもしれません。

Your answer might help someone💌