LoginSignup
24
14

More than 5 years have passed since last update.

PHPのiterableとTraversableは違う

Last updated at Posted at 2019-02-12

PHPのiterable型とTraversableインターフェイスはどういう性質があるのか?異なる点は何か?どういう関係か?について説明する。

iterable

  • いわゆる疑似型で、arrayもしくはTraversableインターフェイスを実装したクラスを指す型。
  • foreachで反復できる。
  • yield fromのジェネレーター構文が使える。
  • PHP7.1で導入された。Traversableインターフェイスより新しい。

Traversableインターフェイス

  • このインターフェイスを実装したオブジェクトはforeachで反復できるようになる。
  • 内部エンジンのインターフェイスであるため、PHPコードでこのインターフェイスを直接実装することはできない特殊なインターフェイスである。
  • PHP5で追加された。
class SomeClass implements Traversable {}
//=> Fatal error: Class SomeClass must implement interface Traversable as part of either Iterator or IteratorAggregate
  • 実装できないだけで、型宣言で用いたり、他のインターフェイスがTraversableインターフェイスを継承することはできる。
interface SomeInterface extends Traversable {} // ok
$obj instanceof Traversable; // ok
function (Traversable $traversable) {} // ok

is_iterable()関数

  • 変数の内容が反復可能な値であることを確認する関数。
is_iterable ( mixed $var ) : bool
  • iterable疑似型、つまり、arrayTraversableのときtrueが返る。
assert(is_iterable([])); // (1) array
assert(is_iterable(new ArrayIterator())); // (2) Traversable
assert(is_iterable((function (): iterable { yield; })())); // (3) Generator

ちなみに(3)はジェネレータ構文を使ったクロージャーを呼び出した結果だが、これはGeneratorクラスとして評価される:

$closure = function (): iterable { yield; };
echo get_class($closure()); //=> Generator

そういえばobjectforeachできたよね……?

PHPはオブジェクトもforeachで反復することができる。

$obj = new stdClass();
$obj->key1 = null;
foreach ($obj as $k => $v) {
    echo $k, PHP_EOL; //=> key1
}

しかし、is_iterable関数ではfalseになる。

$obj = new stdClass();
$obj->key1 = null;
assert(!is_iterable($obj));

iterableTraversableの関係性

  • Traversableiterableである。
  • arrayiterableである。
  • arrayTraversableではない。
  • GeneratorTraversableであり、よってiterableでもある。
  • **IteratorTraversableであり、よってiterableでもある。
  • Traversableを実装していないオブジェクトはiterableではない。(foreachで回せるが)

iterable-2.png

合わせて読みたい

24
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
14