未経験からweb系プログラマーになるための独学履歴~定義済みインターフェイスって何？ Iterator編~

##このコーナーについて

 私は根っからの文系なのでプログラミングや情報技術についてはITパスポート程度の知識しかなく、現在は全くの独学でコードや言語等のスキルの勉強はチュートリアル等でコードを書いて成果物を作りながら学んでいけるが、それらの過程で出てくる用語や技術についてはイマイチ学びきれない。
なので、折に触れて書籍及びQlita記事等のネットサーフィンで学んだ座学的知識をアウトプットすることがこのコーナーの目的である。

## 今回

パーフェクトPHPの定義済みインターフェイスの場所に詳しい使い方はマニュアルを見てくれと書いてあったので、マニュアルを見たところさっぱりわからない。
なので、そもそも定義済みインターフェイスとは一体というところから調べようとしてもどこも「詳しくはマニュアル」の一点張り。
仕方がないので、今回マニュアルを1から解読して理解をするしかいないというのが事の発端。

## 本題

```php:index.php

<?php
class myIterator implements Iterator {
    private $position = 0;
    private $array = array(
        "firstelement",
        "secondelement",
        "lastelement",
    );  

    public function __construct() {
        $this->position = 0;
    }

    public function rewind() {
        var_dump(__METHOD__);
        $this->position = 0;
    }

    public function current() {
        var_dump(__METHOD__);
        return $this->array[$this->position];
    }

    public function key() {
        var_dump(__METHOD__);
        return $this->position;
    }

    public function next() {
        var_dump(__METHOD__);
        ++$this->position;
    }

    public function valid() {
        var_dump(__METHOD__);
        return isset($this->array[$this->position]);
    }
}

$it = new myIterator;

foreach($it as $key => $value) {
    var_dump($key, $value);
    echo "\n";
}
?>



```

マニュアルからそのまま引用。
定義済みインターフェイスというのは要はPHPが用意してくれている、デフォルトのインターフェイスである。
インターフェイスというのは複数のクラスに共通の機能を実装させたい時に、定義することで実体（具体的な値や処理）を定義することなく、メソッドを定義することで特定のオブジェクトが特定の機能（メソッド）を有することが保証されるという仕組みである。
例えば、上記のコードはIteratorという定義済みインターフェイスを用いているのだが元となるIteratorインターフェイスは以下のようになっている。

```php:Iterator

Iterator extends Traversable {
/* メソッド */
abstract public current ( void ) : mixed
abstract public key ( void ) : scalar
abstract public next ( void ) : void
abstract public rewind ( void ) : void
abstract public valid ( void ) : bool
}


```

コードを見ればわかるように、メソッドだけが定義され具体的な処理や値は定義されていない。
このような状態を実体のないメソッドであるといい、実際にインターフェイスが使用される際にオーバーライドされ、処理や値が定義されたとき初めて実体を持つということになる。
インターフェイスやオーバーライドなどについては順番が前後するが、また別に纏めるので今回はこの辺りで。

閑話休題、最初のコードに話は戻る。
$itは当然myIteratorオブジェクトということになる。
さて、上記の関数を見るとPHPビギナーの私には

foreach (配列変数 as キー変数 => 値変数){
  実行する処理1;
  実行する処理2;
}

という関数が思い出される。
これはある繰り返しの処理が行われる度に配列に含まれる要素の値を値変数に、同時にキーの値をキー変数に代入するという関数である。

参考：[PHP入門 foreach文でキーと値を取り出す
](https://www.javadrive.jp/php/for/index9.html)

しかし、ここで私は思う。繰り返しは一体どこにあるのか？ と。
ここで出てくるのがオブジェクトの反復処理という考え方である。

参考：[マニュアル](https://www.php.net/manual/ja/language.oop5.iterations.php)

このマニュアルを見ると、驚くことに上記マニュアルや今回のコードのようにクラス定義、インスタンス宣言及びforeach文を書くと
クラス（オブジェクト）の全てのアクセス権限があるプロパティは、反復処理に使用することができると書いてある。
つまり、この形で書くと自動的にオブジェクトはその処理を繰り返しで行うと定義されるということになる。


なので、これを実行すると

```PHP:
string(18) "myIterator::rewind"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"
int(0)
string(12) "firstelement"

string(16) "myIterator::next"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"
int(1)
string(13) "secondelement"

string(16) "myIterator::next"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"
int(2)
string(11) "lastelement"

string(16) "myIterator::next"
string(17) "myIterator::valid"
```

と以上のように出力される。


ここまで見ればわかるが今回の例はIteratorインターフェイスを用いて、foreach文を使用し、Iteratorインターフェイスのメソッドがどのような順番で呼び出されるか（=どのような処理の工程を踏んでいるか）ということを明らかにするためのものである。
つまり、このインターフェイスを使うとforeach文によるオブジェクトの反復が行えるようになり、そのためにPHP側がデフォルトとして用意したのがIteratorインターフェイスなのである。

後学のために処理を解読すると、以下のようになる

1.rewindメソッドによって$positionに値が代入される（後述するが今回はクラスに格納された配列の中の値を格納されている順番で並べるので初期位置である0が代入される)

2.validメソッドで配列の中の$positionに対応する位置にある変数にアクセスしissetで存在証明する。

3.currentメソッドで2で存在証明したものを値として返す。要はここで現在位置が定義される。

4.keyメソッドで$positionの値を返す（0が返る）

5.nextメソッドで$positionの値が1加算される（次の繰り返しに移る）

以後1~5を繰り返す。

という処理になる。ちなみに各メソッドでそれぞれ実行しているメソッド名をvar_dumpで書き出している。
いくつか分けて取り上げると

```php:
string(18) "myIterator::rewind"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"

string(16) "myIterator::next"
string(17) "myIterator::valid"
string(19) "myIterator::current"
string(15) "myIterator::key"

~（以下繰り返し）
```

まずはこの一群。
これは単純にオブジェクトのメソッドの中にあるvar_dumpに書き出されたものである。
オブジェクトは実行されているのだから当然こうなるだろう。

```php:
int(0)// キー
string(12) "firstelement"//値

int(1)// キー
string(13) "secondelement"// 値

int(2)// キー
string(11) "lastelement"// 値

```

次にこの部分、これがPHPビギナーにとっては少し分かりづらくなりそうなところである。
これは同じva_dumpでもforeach文内のvar_dump($key, $value)で書き出されたものとなる。
つまり、配列のキーとそれに対応する値であるということ。

つまり以下のコードは


```php:
$it = new myIterator;

foreach($it as $key => $value) {
    var_dump($key, $value);
    echo "\n";
 }
```

「myIteratorオブジェクトが繰り返し行われるたびに、オブジェクトの中にある配列に含まれる要素の値を値変数に代入すると同時にキーの値をキー変数に代入して、代入した値変数とキー変数を改行して書き出す」

という処理になる。


## あとがき

パーフェクトPHP、PHP The Right Wayなどで基礎を学習していると、チュートリアルで成果物を作りながらの学習と違い、基礎の部分は学習者の知識レベルや理解力によって思わぬところで理解が滞る可能性があり、自分はまだまだだなということを毎度痛感する。

この記事にて間違った解釈や修正点等々ありましたら、コメント欄にて指摘していただけると大変助かります。