5

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

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

这张纸条说了什么?这是否意味着我们可以在没有任何类的情况下在 foreach 循环中使用IteratorAggregateIterator或者可能是我错了。谁能说出这张纸条是怎么说的??

4

1 回答 1

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() 失败时添加自定义异常,但 caching() , ETC。

您所指的注释意味着PHP的某些内部类(用C代码编写)可能直接实现此接口。任何需要实现 Traversable 的用户态类都必须通过实现 IteratorAggregate 或 Iterator 或其他 Traversable 的后代来实现。参见Kevin McArthur p. 的 Pro PHP。143 楼。

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

Traversable {
}

混淆部分是对象和数组没有实现“可遍历”,但可以被foreach 遍历,但是您不能使用instanceofcheck 或type hint检查 foreach 的兼容性。

$myarray = array('one', 'two', 'three');
$myobj = (object)$myarray;

if ( !($myarray instanceof \Traversable) ) {
    print "myarray is NOT Traversable";
}
if ( !($myobj instanceof \Traversable) ) {
    print "myobj is NOT Traversable";
}

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

PHP 5 提供了一种定义对象的方法,因此可以使用例如 foreach 语句来遍历项目列表。默认情况下,所有可见属性都将用于迭代。

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

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

于 2017-09-29T03:02:26.663 回答