5

わかりました。タイトルにあるように、単純なforeachループよりもArrayIteratorを使用する主な利点は何ですか。

コンテナとして使用されているオブジェクトがあります。その主な責任は、オブジェクトの配列を格納することです。

誰かが私のクラスにIteratorAggregateを実装させ、オブジェクトの配列を含むArrayIteratorを次のように返すように提案しました。

  public function getIterator()
  {  
    return new ArrayIterator($this->_objs);  
  }

単に配列を返し、標準のforeachを使用してそれらをループするのとは対照的に、これには何の利点もありません。

なぜこれが良い考えになるのか誰かが説明できますか?

4

2 に答える 2

7

実装の利点ArrayAccessは単純です。オブジェクト全体にアクセスすることもprivate、配列として非常に特定のプロパティにアクセスすることもできます。

この非常に単純な例では、とを使用IteratorArrayAccessて、という名前の特定のプロパティにアクセスします$array

class Foo implements \ArrayAccess, \Iterator
{
    public $pointer = 0;

    private $array = [
        'first value',
        'second value',
        'third value',
    ];

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

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

    public function key()
    {
        return $this->pointer;
    }

    public function next()
    {
        ++$this->pointer;
    }

    public function rewind()
    {
        $this->pointer = 0;
    }

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

これで、すべての配列をループするようにループできます。

$foo = new Foo();
foreach ( $foo as $key => $value )
{
    print "Index: {$key} - Value: {$value}".PHP_EOL;
}

前の例で見たように、トラフをループしてすでに存在するデータにアクセスするためだけに、これらすべてのメソッドを実装する必要があります。そして、ArrayAccess実際に値を設定できるようにするを実装するには、別のメソッドのセットを実装する必要があります。

ArrayAccess {
    abstract public boolean offsetExists ( mixed $offset )
    abstract public mixed offsetGet ( mixed $offset )
    abstract public void offsetSet ( mixed $offset , mixed $value )
    abstract public void offsetUnset ( mixed $offset )
}

これで、を使用するだけで、その(current / key / next / etc)一連のメソッドの記述と繰り返しを完全に省くことができますIteratorAggregateこれはそれを単一の必須のメソッドに合計します:getIterator()

これで、次のような結果のクラスが作成されます。

class Bar implements \ArrayAccess, \IteratorAggregate
{
    private $array = [];

    public function getIterator()
    {
        return new ArrayIterator( $this->array );
    }
}

$arrayそして、classesプロパティへの完全な配列アクセスがあります。値を設定および設定解除したり、値が返されるかどうかを確認issetしたり、ループしたりすることができます。はるかに便利です。そして、を実装するだけで、上記の8つのメソッドすべてとまったく同じことをIteratorAggregate実行します。

最後の注意:おそらくもう1つのステップを実行し、同様に実装Traversableします。このインターフェイスは、実装開発者がどちらを使用する必要があるかを明示的に指定せずに、実装Iteratorまたは必須のいずれかを作成できるため、非常に便利です。IteratorAggregateオブジェクトがループ可能でなければならないことが必須であることを説明しているだけです。

$foo = new IteratorContainerController();
$foo->addDependency( Traversable $bar );

これは、の依存関係IteratorContainerController()が常にIteratorまたはIteratorAggregate実装されたオブジェクトのいずれかになることを意味します。したがって、誰かが単純に入力するIteratorAggregateか、よりきめ細かい制御が必要な場合、または変数が設定される前に変数の前処理を行う場合は、単純にを使用できますIterator

于 2013-12-15T16:34:54.713 に答える
-2

配列を返すと、オブジェクトの内部構造が公開されます。イテレータの使用はより抽象的です。

あなたのクラスが何をしているのか、あなたの場合はどちらがより適切なのかわかりません。ただし、一般的な経験則として、現実的なユースケースがデータを反復処理することだけである場合は、イテレータを返す必要があります。

于 2012-05-29T02:15:40.957 に答える