クラス構文繰り返し・反復処理

【PHP】参照で連結されたクラスをforeachで列挙する

更新日:2019/12/24

次のようなクラスがあるとする。


class A
{
    private $nextA;
}

$nextAに次のAへの参照を格納し、不特定多数のAを連結する。

これをforeach()で列挙できるようにしたい。

 

配列なら楽

クラスの中に配列を作成してforeach()で取り出すなら、次のようにすればいい。


class A implements IteratorAggregate
{
    private $arrays=[];
    public function __construct()
    {
        // $arraysに値をセット
    }
    function getIterator()
    {
        return new ArrayIterator($this->arrays);
    }
}

$b = new A();
foreach($b as $val){
・・・
}

これで$arrays内の要素が順番に取り出せる。

しかし僕のやりたいことは、これではダメなようだ。

 

Iterator(イテレータ)インターフェイスを実装する

上の配列の例は、Iteratorインターフェースを利用したもの。
このインターフェースの説明は、こちらを見てください。

外部のイテレータあるいはオブジェクト自身から反復処理を行うためのインターフェイスです。

Iterator インターフェイスより引用

上の例のgetIterator()関数内で使用されているArrayIteratorクラスは、配列を処理してくれるIteratorインターフェースのようです。

そこでArrayIterator()の代わりに、クラスへの参照を処理してくれるインターフェースを作成すればうまくいきそうです。


class AIterator implements Iterator
{
    private $org;    // 初期値を格納しておく変数
    private $cur;    // 現在のクラス
    private $key=0;    // 現在のキー(0からの連番)

    function __construct(a $p)
    {
        $this->org = $p;    // 初期値をセット
        $this->cur = $p;
    }

    function rewind()    // 初期値にリセット
    {
        $this->cur = $this->org;
        $this->key=0;
    }

    function current()    // 現在のクラスを返す
    {
        return $this->cur;
    }

    function key()    // 現在のキーを返す
    {
        return $this->key;
    }

    function next()    // 内部的に次のクラスへ進める
    {
        $this->cur=$this->cur->nextNode();
        ++$this->key;
    }

    function valid()    // 現在のクラスが範囲内かどうか
    {
        return false !== $this->cur;
    }
}

このインターフェースをArrayIteratorクラスの代わりに実装して、Aクラス内に次のクラスのセット及び取得する関数を作成します。


class A implements IteratorAggregate
{
    private $nextA=false;
    private $val;

    public function __construct($val)
    {
        $this->val = $val;
    }
    public function setNext($next)  // 次のクラスAをセット
    {
        $this->nextA = $next;
    }

    public function nextNode()  // 次のクラスAを取得
    {
        return $this->nextA;
    }

    function getIterator()
    {
        return new AIterator($this);
    }
}

Aクラスを構築後foreach()で列挙します。


$st = new a(0);
$current = $st;

for($i = 1 ; $i < 10 ; $i++){
    $ac = new a(strval($i));
    $current->setNext($ac);
    $current = $ac;
}

foreach ($st as $key => $nw){
    echo $key . ' : ' . $nw->text() . "\n";
}

// 実行結果
0 : 0
1 : 1
2 : 2
3 : 3
4 : 4
5 : 5
6 : 6
7 : 7
8 : 8
9 : 9

うまくいきました。
\(^o^)/

更新日:2019/12/24

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。