Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP SPL ArrayIterator v simple foreach_Php_Spl - Fatal编程技术网

PHP SPL ArrayIterator v simple foreach

PHP SPL ArrayIterator v simple foreach,php,spl,Php,Spl,好的,正如标题所说:在一个简单的foreach循环上使用ArrayIterator的主要好处是什么 我有一个用作容器的对象,它的主要职责是存储一个对象数组 有人建议我让我的类实现IteratorAggregate并返回一个ArrayIterator,其中包含我的对象数组,如下所示: public function getIterator() { return new ArrayIterator($this->_objs); } 与简单地返回数组然后使用标准fo

好的,正如标题所说:在一个简单的foreach循环上使用ArrayIterator的主要好处是什么

我有一个用作容器的对象,它的主要职责是存储一个对象数组

有人建议我让我的类实现IteratorAggregate并返回一个ArrayIterator,其中包含我的对象数组,如下所示:

  public function getIterator()
  {  
    return new ArrayIterator($this->_objs);  
  }
与简单地返回数组然后使用标准foreach在其上循环相比,我看不出这有什么好处


有人能解释一下为什么这是个好主意吗?

返回数组会暴露对象的内部结构。使用迭代器更抽象


我不知道你们班做什么,或者哪个更适合你们的情况。但是作为一般的经验法则,如果唯一实际的用例是对数据进行迭代,那么您应该返回一个迭代器。

实现
ArrayAccess
的好处很简单:您可以访问整个对象,或者只访问非常特定的,甚至是
private
属性作为数组

在这个非常简单的示例中,我们使用
Iterator
ArrayAccess
来访问名为
$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 );
    }
}
我们对class
$array
属性具有完全的数组访问权限。我们可以设置和取消设置值,检查它们是否返回
isset
,可以循环使用它们等等。更方便。它的功能与上述八种方法完全相同,只需实现
IteratorAggregate

最后一点注意:您可能还要执行一个步骤并实现
Traversable
。这个接口非常好,因为它允许您强制实现
Iterator
IteratorAggregate
,而无需明确说明实现开发人员需要使用哪个接口。它只是解释了对象必须是可循环的是强制性的

$foo = new IteratorContainerController();
$foo->addDependency( Traversable $bar );
这意味着
IteratorContainerController()
的依赖项将始终是
Iterator
IteratorAggregate
实现的对象。因此,有人可以简单地将一个
迭代器
放入,或者,如果他/她需要更细粒度的控制,或者在设置变量之前对变量进行预处理,他/她可以简单地使用
迭代器

,这对你来说很有趣。