Изменяет ли состояние / содержание объектов в соответствии с использованием итератора (php) - PullRequest
1 голос
/ 12 июля 2011

Рассмотрим объект, используемый для хранения коллекции предметов, но эта коллекция может варьироваться в зависимости от предопределенных контекстов.

Class Container implements IteratorAggregate (
  protected $contexts; // list of associated contexts, example: array(0=>1,1=>3)
  protected $contents; // array
  public loadContents( $contextId ) { /* populates $this->contents*/ }
  public getContexts() { /* populates $this->contexts */ }
  ...
  public function getIterator() { return new ArrayIterator($this->contents); }
  public getContextIterator() { return new contextIterator($this); }
}

Итератор выглядит так:

Class contextIterator {
  protected $container;
  protected $contexts;
  protected $currentContext;

  public function __construct($container) {
    $this->container = $container;
    $this->contexts = $container->getContexts();
    $this->currentContext = 0;
  }

  public current() {
    $this->container->loadContents( $this->key() );
    return $this->contexts[ $this->key() ];
  }

  public function key() { return $this->currentContext; }
  public function next() { $this->currentContext++; }
  public function rewind() { $this->currentContext = 0; }
  public function valid() { return isset( $this->contexts[ $this->key() ] ); }
}

В тех немногих случаях, когда каждый контекст необходимо проверять итеративно, я делаю следующее:

$myContainer = new Container();
foreach( $myContainer->getContextIterator() as $key => $value ) {
  $myContainer->someMethod();
}

Выше это красиво и компактно, но мне это кажется грязным, поскольку я никогда не использую $ key или $ value. Является ли использование итератора излишним? Кроме того, должен ли итератор когда-либо изменять состояние / содержимое объекта, который он итерирует?

1 Ответ

1 голос
/ 12 июля 2011

Выше это красиво и компактно, но мне это кажется грязным, поскольку я никогда не использую $ key или $ value.

Вы не показали внутренности getContextIterator(), поэтому трудно сделать конкретные предложения. Как правило, в PHP можно создавать объекты с возможностью итерации, реализуя OuterIterator взаимодействия или просто реализуя Iterator интерфейс . Оба интерфейса предопределены, и вы можете использовать свой объект с next(), foreach и т. Д.

Полагаю, вы реализовали что-то , например OuterIterator. Если вы внедрите OuterIterator вместо этого, вы получите некоторое преимущество в скорости AFAIK.

Используете ли вы итератор излишним?

Нет, не скажу так. Итераторы очень хороши для коллекций, так как вы сказали, что они есть. Я просто изменил бы его на итератор SPL.

Кроме того, должен ли итератор когда-либо изменять состояние / содержимое объекта, который он итерирует?

Ну, на самом деле каждый итератор делает это, по крайней мере, для внутреннего указателя итерации. Но я думаю, что это не твоя забота, но, возможно, уже светлее.

Так что даже для "большего" изменения внутри объекта, который вы перебираете, совершенно нормально, что он изменяется, пока ясно, что он делает. Контрпример: если вы перебираете массив и он будет перетасовывать элементы каждый раз, когда итерация идет на шаг вперед, это не будет полезно.

Но есть и другие случаи, когда это полностью допустимо и полезно. Так что решайте, что сделано, а не по общему правилу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...