我们可以在php的foreach循环中使用IterateAggregate或Iterator吗?

时间:2017-09-29 02:16:43

标签: php foreach traversable

我是php的初学者,从php.net学习它。该页面上的注释http://php.net/manual/en/class.traversable.php)表示:

实现此接口的内部(内置)类可以在foreach构造中使用,而不需要实现IteratorAggregate或Iterator。

注意说什么?这是否意味着我们可以在没有任何类的情况下在foreach循环中使用 IteratorAggregate Iterator ,或者可能是我错了。任何人都可以说这注意是什么意思?

1 个答案:

答案 0 :(得分:2)

IteratorAggregate界面,用于创建外部迭代器,允许您使用foreach遍历自定义类对象

class FooBarClass implements IteratorAggregate
{
    public $property = "Nothing to see";

    public function __construct()
    {
    }

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

$obj = new FooBar;

foreach($obj as $key => $value) {
    print(var_dump($key, $value) . "\n");
}

Iterator也是外部迭代器的接口,但允许您的类或对象在内部进行迭代:

class myIterator implements Iterator
{
    private $position = 0;
    private $array = array('one', 'two', 'three');

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

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

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

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

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

尽管如此,您仍然可以使用与IteratorAggregate相同的方式遍历对象。

两者之间的区别在于IteratorAggregate比迭代器更容易实现,而且通常更快。缺点是它只是用于遍历而不提供next(),key()等方法,因为在foreach遍历期间不会调用它们。

虽然Iterator(或更具体的OuterIterator或(更简单)和IteratorIterator)允许您更好地控制对象的迭代并添加自定义例外next(),key()或prev()失败,缓存()等

您所指的注释意味着PHP的一些内部类(用C代码编写)可以直接实现此接口。任何需要实现Traversable的userland类都必须通过实现IteratorAggregate或Iterator或者来自Traversable的其他类来实现。见Pro PHP by Kevin McArthur p。 143F。

Traversable接口本身是一个抽象的基本接口(没有接口概要中所示的方法),无法实例化。但是,它可用于检查类是否可以使用foreach进行遍历。

Traversable {
}

混淆部分是对象和数组实现“Traversable”,但是can be traversed是foreach,但是你不能使用{检查foreach兼容性{1}}检查或type hint

instanceof

如前所述,每个对象都可以使用foreach遍历,但是您可以访问公共属性。引用Object Iteration上的PHP手册:

  

PHP 5提供了一种定义对象的方法,因此可以实现   迭代一个项目列表,例如foreach   声明。默认情况下,所有可见属性都将用于   迭代。

因此,如果您使用private和protected值封装对象并编写getter和setter方法来访问它,您可能希望您的类实现IteratorAggregate或Iterator并编写逻辑以根据需要在foreach循环中访问这些值。

简而言之,实现Traversable接口的对象(通过Iterator或IteratorAggregate)“就像一个数组”。但是,没有必要迭代对象。但是如果你想改变他们的行为,你需要实现Iterator。相同的逻辑适用于内置类。