PHP Iterator接口:current()返回底层数组而不是第一个值

时间:2017-07-24 13:06:05

标签: php arrays iterator iteration

我正在创建一个实现IteratorArrayAccess的类。迭代器测试失败了。当我在print_r()上执行current($object)时,我获得了底层数组,而不是第一个对象。

以下代码是我实际课程中展示问题的示例。这是我第一次在我的一个课程中实现Iterator,所以我可能在某个地方做错了。我需要更改什么才能使迭代器正常工作?

代码:

class Collection implements \ArrayAccess, \Iterator
{
    private $_array = array();

    public function __invoke() { return $this->_array; }
    public function offsetExists($offset) { return array_key_exists($offset, $this->_array); }
    public function offsetGet($offset) { return $this->_array[$offset]; }
    public function offsetSet($offset, $value) { $this->_array[$offset] = $value; }
    public function offsetUnset($offset) { unset($this->_array[$offset]); }
    public function current() { return current($this->_array); }
    public function key() { return key($this->_array); }
    public function next() { return next($this->_array); }
    public function rewind() { return reset($this->_array); }
    public function valid() { return is_null(key($this->_array)); }
}

class TemporaryTest extends \PHPUnit\Framework\TestCase
{

    private $_test_object;

    public function setUp()
    {
        $this->_test_object = new Collection();
        $this->_test_object['alpha'] = 'blah';
        $this->_test_object['beta'] = 'yada';
        $this->_test_object['gamma']  = 'woot';
    }

    public function testIteratorOnInternalArray()
    {
        $o = $this->_test_object;
        $a = $o();
        $this->assertEquals('blah', current($a));
        $this->assertEquals('yada', next($a));
        $this->assertEquals('woot', next($a));
    }

    public function testIterator()
    {
        print_r(current($this->_test_object));
        $this->assertEquals('blah', current($this->_test_object));
        $this->assertEquals('yada', next($this->_test_object));
        $this->assertEquals('woot', next($this->_test_object));
        $this->assertFalse($this->_test_object->valid());
        reset($this->_test_object);
        $this->assertEquals('blah', current($this->_test_object));
    }

    public function testForEach()
    {
        $actual = array();
        foreach ($this->_test_object as $key => $value) { $actual[$key] = $value; }
        $this->assertEquals(array('alpha' => 'blah', 'beta' => 'yada','gamma' =>  'woot'), $actual);
    }
}

单位测试输出:

.FArray
(
    [alpha] => blah
    [beta] => yada
    [gamma] => woot
)
F                                                                 3 / 3 (100%)

There were 2 failures:

1) TemporaryTest::testIterator
Array (...) does not match expected type "string".

/Users/mac/Projects/NetShapers/Gears/core/Tests/Unit/TemporaryTest.php:83

2) TemporaryTest::testForEach
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    'alpha' => 'blah'
-    'beta' => 'yada'
-    'gamma' => 'woot'
 )

/Users/mac/Projects/NetShapers/Gears/core/Tests/Unit/TemporaryTest.php:97

1 个答案:

答案 0 :(得分:1)

你期待什么?

当您致电current($a)时,您实际上是在集合上调用系统函数current(),而不是内部方法Collection::current()

只需按照这样的方式来获得你想要的东西:

$this->assertEquals('blah', $a->current());

如果您可以在foreach中使用您的收藏,系统会自动调用这些方法。

  

评论后的其他修正。

valid方法出错,这就是foreach失败的原因。

宣言应该是这样的:

public function valid() 
{ 
    return !is_null(key($this->_array));
}