[英]PHP Iterator interface: current() returns underlying array instead of first value
I'm creating a class that implements Iterator
and ArrayAccess
. 我正在创建一个实现
Iterator
和ArrayAccess
。 The iterator tests are failing. 迭代器测试失败。 When I do a
print_r()
on current($object)
, I get the underlying array, not the first object. 当我在
current($object)
print_r()
上执行print_r()
时,我得到了基础数组,而不是第一个对象。
The code below is a sample from my actual class that demonstrates the issue. 下面的代码是我实际班级中的一个示例,它演示了该问题。 This is the first time I have implemented
Iterator
in one of my classes, so I'm probably doing this wrong somewhere. 这是我第一次在一个类中实现
Iterator
,所以我可能在某个地方做错了。 What do I need to change to make the iterator work properly? 为了使迭代器正常工作,我需要更改什么?
Code: 码:
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);
}
}
Unit test output: 单元测试输出:
.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
What did you expect? 您期望什么?
When you call current($a)
you actually call system function current()
on your collection, not the internal method Collection::current()
. 调用
current($a)
,实际上是在集合上调用系统函数current()
,而不是内部方法Collection::current()
。
Just calll it like this to get what you want: 像这样调用它就可以得到您想要的:
$this->assertEquals('blah', $a->current());
These methods would be called automatically by the system if you could use your collection in foreach
for example. 例如,如果您可以在
foreach
使用您的集合,则系统会自动调用这些方法。
Additional fixes after comment.
评论后的其他修复。
You have an error in valid
method, that's why foreach
fails for you. 您的
valid
方法有误,这就是为什么foreach
对您失败的原因。
Declaration should look like that: 声明应如下所示:
public function valid()
{
return !is_null(key($this->_array));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.