0

私は本から PHP の OOP について学んでいますが、Iterators と Iteration のセクションには困惑しています。

私が理解していることについては、オブジェクトの属性をループするには、組み込みクラス Iterator を実装する必要があると思います。次に、IteratorAggregate インターフェースを実装し、その中に getIterator メソッドを作成します。しかし、私は現在、これらの各要素が果たす役割と、それらをどのような形式で記述する必要があるかについて混乱しています。言い換えれば、これらの概念の簡単な (平易な英語の) 説明と簡単な例を探しているだけです。どんな助けでも大歓迎です!!!!!

そして、あなたの時間と前もって助けてくれてありがとう!!!!

4

2 に答える 2

2

ループしたいものは実装する必要がありますTraversableTraversableただし、直接実装することはできません。そのサブタイプの 1 つを実装する必要があります。どのように行うかは、オブジェクトがどのように使用されるかによって異なります。

必要に応じて、実装することもできますIterator。あなたのタイプがすでに前方のみのリストであることを意図している場合、それは十分に機能します。イテレータを作成することにした場合、実装するメソッドが 5 つあります。

  • current、現在の場所の値を取得します。
  • key、現在の場所のキーを取得します。
  • next、次の場所に進みます。
  • rewind、現在の場所を最初にリセットします。と
  • validfalse、反復が反復されているもののリストの最後から外れている場合に返されます。

PHP は、反復の過程でこれらのメソッドを呼び出します。具体的には、次のようなコードがあるとします。

foreach ($it as $key => $value) {
    doStuffWith($key, $value);
}

これは、以下とほぼ同等です。

for ($it->rewind(); $it->valid(); $it->next()) {
    $value = $it->current();
    $key = $it->key(); // only if the foreach has a `$key =>`

    doStuffWith($key, $value);
}

implements Iterator基本的には、大まかにその順序で呼び出されるメソッドに適切に応答するタイプを構築するだけです。理想的には、その間に何かが発生する可能性もあるはずです...しかし、参照を渡している場合を除き、通常は問題になりません。

カスタム反復が必要ない場合は、代わりに を実装しIteratorAggregate、必要なことができる場合は既存の反復子型を返すことができます。(たとえば、内部配列のループを許可したい場合はArrayIterator、そのジョブ用の が既に用意されています。自分で作成する必要はありません。) の場合は、トラバース可能なものを返すIteratorAggregateを実装するだけで済みます。これは、組み込みの SPL iteratorsgetIteratorのいずれかで既にトラバースできるものがある場合、または配列などに簡単に縮小できるものがある場合に適したソリューションです。

上記の同じループが IteratorAggregate で呼び出された場合、次のようになります。

foreach ($it->getIterator() as $key => $value) {
    doStuffWith($key, $value);
}

getIterator()の実装かIterator、配列のようなプリミティブなトラバース可能なものを返す必要があります。

Java スタイルの反復子については、その場所を記憶してコレクションをループできる Iterator サブタイプを構築し、コレクションに実装IteratorAggregateして反復子型のインスタンスを返すことができます。

于 2013-03-15T20:17:25.890 に答える
0

基本的な機能については、、、、およびメソッドimplement Iteratorに関連する機能を追加するだけで十分です。以下に例を示します。rewindvalidkeycurrentnext

  /**
   * Awesome
   *
   * Do awesome stuff
   */
  final class Awesome implements Iterator
  {

    /**
     * An array of data
     *
     * @access private
     * @var array $_data
     */
    private $_data;

    /**
     * Store the initial data
     *
     * @access public
     * @param array $data
     */
    public function __construct(array $data = array())
    {
      $this->_data = $data;
    }

    /**
     * Rewind the iterator
     *
     * @access public
     */
    public function rewind()
    {
      reset($this->_data);
    }

    /**
     * Validate the existence of the next element
     *
     * @access public
     * @return boolean
     */
    public function valid()
    {
      return isset($this->_data[$this->key()]);
    }

    /**
     * Return the current key
     *
     * @access public
     * @return integer
     */
    public function key()
    {
      return key($this->_data);
    }

    /**
     * Return the current value
     *
     * @access public
     * @return mixed
     */
    public function current()
    {
      return current($this->_data);
    }

    /**
     * Increment the iteration index
     *
     * @access public
     */
    public function next()
    {
      next($this->_data);
    }

  }

  // Instantiate a new Awesome object
  $awesome = new Awesome(array('Michael', ' ', 'Rushton', ' ', 'is', ' ', 'awesome', '!'));

  // Iterate over the awesome object and output a universal truth
  foreach ($awesome as $almost_awesome)
  {
    echo $almost_awesome;
  }

代わりにオブジェクトのプロパティを反復処理する場合は、単純に次のように変更__constructします。

/**
 * Construct the object
 *
 * @access public
 */
public function __construct()
{

  // Get the properties
  $object_vars = get_object_vars($this);

  // Unset the data reference
  unset($object_vars['_data']);

  // Set the data
  $this->_data = $object_vars;

}
于 2013-03-15T20:13:04.913 に答える